258 lines
11 KiB
Plaintext
258 lines
11 KiB
Plaintext
[section boost/python/operators.hpp]
|
|
[section Introduction]
|
|
<boost/python/operators.hpp> provides types and functions for automatically generating Python [@http://www.python.org/doc/ref/specialnames.html special methods] from the corresponding C++ constructs. Most of these constructs are operator expressions, hence the name. To use the facility, substitute the [link high_level_components.boost_python_operators_hpp.object_self self] object for an object of the class type being wrapped in the expression to be exposed, and pass the result to [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu class_<>::def()]. Much of what is exposed in this header should be considered part of the implementation, so is not documented in detail here.
|
|
[endsect]
|
|
[section Class `self_ns::self_t`]
|
|
`self_ns::self_t` is the actual type of the [link high_level_components.boost_python_operators_hpp.object_self self] object. The library isolates `self_t` in its own namespace, `self_ns`, in order to prevent the generalized operator templates which operate on it from being found by argument-dependent lookup in other contexts. This should be considered an implementation detail, since users should never have to mention `self_t` directly.
|
|
``
|
|
namespace boost { namespace python { namespace self_ns {
|
|
{
|
|
unspecified-type-declaration self_t;
|
|
|
|
// inplace operators
|
|
template <class T> operator_<unspecified> operator+=(self_t, T);
|
|
template <class T> operator_<unspecified> operator-=(self_t, T);
|
|
template <class T> operator_<unspecified> operator*=(self_t, T);
|
|
template <class T> operator_<unspecified> operator/=(self_t, T);
|
|
template <class T> operator_<unspecified> operator%=(self_t, T);
|
|
template <class T> operator_<unspecified> operator>>=(self_t, T);
|
|
template <class T> operator_<unspecified> operator<<=(self_t, T);
|
|
template <class T> operator_<unspecified> operator&=(self_t, T);
|
|
template <class T> operator_<unspecified> operator^=(self_t, T);
|
|
template <class T> operator_<unspecified> operator|=(self_t, T);
|
|
|
|
// comparisons
|
|
template <class L, class R> operator_<unspecified> operator==(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator!=(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator<(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator>(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator<=(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator>=(L const&, R const&);
|
|
|
|
// non-member operations
|
|
template <class L, class R> operator_<unspecified> operator+(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator-(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator*(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator/(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator%(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator>>(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator<<(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator&(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator^(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> operator|(L const&, R const&);
|
|
template <class L, class R> operator_<unspecified> pow(L const&, R const&);
|
|
|
|
// unary operations
|
|
operator_<unspecified> operator-(self_t);
|
|
operator_<unspecified> operator+(self_t);
|
|
operator_<unspecified> operator~(self_t);
|
|
operator_<unspecified> operator!(self_t);
|
|
|
|
// value operations
|
|
operator_<unspecified> int_(self_t);
|
|
operator_<unspecified> long_(self_t);
|
|
operator_<unspecified> float_(self_t);
|
|
operator_<unspecified> complex_(self_t);
|
|
operator_<unspecified> str(self_t);
|
|
|
|
operator_<unspecified> repr(self_t);
|
|
}}};
|
|
``
|
|
The tables below describe the methods generated when the results of the expressions described are passed as arguments to [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu class_<>::def()]. `x` is an object of the class type being wrapped.
|
|
[section `self_t` inplace operators]
|
|
In the table below, If `r` is an object of type [link high_level_components.boost_python_operators_hpp.class_template_other other<T>], `y` is an object of type `T`; otherwise, `y` is an object of the same type as `r`.
|
|
[table
|
|
[[C++ Expression][Python Method Name][C++ Implementation]]
|
|
[[`self += r`][`__iadd__`][`x += y`]]
|
|
[[`self -= r`][`__isub__`][`x -= y`]]
|
|
[[`self *= r`][`__imul__`][`x *= y`]]
|
|
[[`self /= r`][`__idiv__`][`x /= y`]]
|
|
[[`self %= r`][`__imod__`][`x %= y`]]
|
|
[[`self >>= r`][`__irshift__`][`x >>= y`]]
|
|
[[`self <<= r`][`__ilshift__`][`x <<= y`]]
|
|
[[`self &= r`][`__iand__`][`x &= y`]]
|
|
[[`self ^= r`][`__ixor__`][`x ^= y`]]
|
|
[[`self |= r`][`__ior__`][`x |= y`]]
|
|
]
|
|
[endsect]
|
|
[section `self_t` comparison functions]
|
|
In the tables below, if `r` is of type [link high_level_components.boost_python_operators_hpp.class_self_ns_self_t self_t], `y` is an object of the same type as `x`;
|
|
if `l` or `r` is an object of type [link high_level_components.boost_python_operators_hpp.class_template_other other<T>], `y` is an object of type `T`;
|
|
otherwise, `y` is an object of the same type as `l` or `r`.
|
|
`l` is never of type [link high_level_components.boost_python_operators_hpp.class_self_ns_self_t self_t].
|
|
|
|
The column of Python Expressions illustrates the expressions that will be supported in Python for objects convertible to the types of x and y. The secondary operation arises due to Python's [@http://www.python.org/doc/ref/customization.html#l2h-89 reflection rules] for rich comparison operators, and are only used when the corresponding operation is not defined as a method of the y object.
|
|
[table
|
|
[[C++ Expression][Python Method Name][C++ Implementation][Python Expression (primary, secondary)]]
|
|
[[`self == r`][`__eq__`][`x == y`][`x == y`, `y == x`]]
|
|
[[`l == self`][`__eq__`][`y == x`][`y == x`, `x == y`]]
|
|
[[`self != r`][`__ne__`][`x != y`][`x != y`, `y != x`]]
|
|
[[`l != self`][`__ne__`][`y != x`][`y != x`, `x != y`]]
|
|
[[`self < r`][`__lt__`][`x < y`][`x < y`, `y > x`]]
|
|
[[`l < self`][`__gt__`][`y < x`][`y > x`, `x < y`]]
|
|
[[`self > r`][`__gt__`][`x > y`][`x > y`, `y < x`]]
|
|
[[`l > self`][`__lt__`][`y > x`][`y < x`, `x > y`]]
|
|
[[`self <= r`][`__le__`][`x <= y`][`x <= y`, `y >= x`]]
|
|
[[`l <= self`][`__ge__`][`y <= x`][`y >= x`, `x <= y`]]
|
|
[[`self >= r`][`__ge__`][`x >= y`][`x >= y`, `y <= x`]]
|
|
[[`l <= self`][`__le__`][`y >= x`][`y <= x`, `x >= y`]]
|
|
]
|
|
[endsect]
|
|
[section `self_t` non-member operations]
|
|
The operations whose names begin with "__r" below will only be called if the left-hand operand does not already support the given operation, as described [@http://www.python.org/doc/current/ref/numeric-types.html#l2h-152 here].
|
|
[table
|
|
[[C++ Expression][Python Method Name][C++ Implementation]]
|
|
[[`self + r`][`__add__`][`x + y`]]
|
|
[[`l + self`][`__radd__`][`y + x`]]
|
|
[[`self - r`][`__sub__`][`x - y`]]
|
|
[[`l - self`][`__rsub__`][`y - x`]]
|
|
[[`self * r`][`__mult__`][`x * y`]]
|
|
[[`l * self`][`__rmult__`][`y * x`]]
|
|
[[`self / r`][`__div__`][`x / y`]]
|
|
[[`l / self`][`__rdiv__`][`y / x`]]
|
|
[[`self % r`][`__mod__`][`x % y`]]
|
|
[[`l % self`][`__rmod__`][`y % x`]]
|
|
[[`self >> r`][`__rshift__`][`x >> y`]]
|
|
[[`l >> self`][`__rrshift__`][`y >> x`]]
|
|
[[`self << r`][`__lshift__`][`x << y`]]
|
|
[[`l << self`][`__rlshift__`][`y << x`]]
|
|
[[`self & r`][`__and__`][`x & y`]]
|
|
[[`l & self`][`__rand__`][`y & x`]]
|
|
[[`self ^ r`][`__xor__`][`x ^ y`]]
|
|
[[`l ^ self`][`__rxor__`][`y ^ x`]]
|
|
[[`self | r`][`__or__`][`x | y`]]
|
|
[[`l | self`][`__ror__`][`y | x`]]
|
|
[[`pow(self, r)`][`__pow__`][`x ** y`]]
|
|
[[`pow(l, self)`][`__rpow__`][`y ** x`]]
|
|
]
|
|
[endsect]
|
|
[section `self_t` unary operations]
|
|
[table
|
|
[[C++ Expression][Python Method Name][C++ Implementation]]
|
|
[[`-self`][`__neg__`][`-x`]]
|
|
[[`+self`][`__pos__`][`+x`]]
|
|
[[`~self`][`__invert__`][`~x`]]
|
|
[[`not self` or `!self`][`__nonzero__`][`!!x`]]
|
|
]
|
|
[endsect]
|
|
[section `self_t` value operations]
|
|
[table
|
|
[[C++ Expression][Python Method Name][C++ Implementation]]
|
|
[[`int_(self)`][`__int__`][`long(x)`]]
|
|
[[`long_(self)`][`__long__`][`PyLong_FromLong(x)`]]
|
|
[[`float_(self)`][`__float__`][`double(x)`]]
|
|
[[`complex_(self)`][`__complex__`][`std::complex<double>(x)`]]
|
|
[[`str(self)`][`__str__`][`lexical_cast<std::string>(x)`]]
|
|
[[`repr(self)`][`__repr__`][`lexical_cast<std::string>(x)`]]
|
|
]
|
|
[endsect]
|
|
[endsect]
|
|
[section Class template `other`]
|
|
Instances of `other<T>` can be used in operator expressions with [link high_level_components.boost_python_operators_hpp.object_self self]; the result is equivalent to the same expression with a `T` object in place of `other<T>`. Use `other<T>` to prevent construction of a `T` object in case it is heavyweight, when no constructor is available, or simply for clarity.
|
|
``
|
|
namespace boost { namespace python
|
|
{
|
|
template <class T>
|
|
struct other
|
|
{
|
|
};
|
|
}}
|
|
``
|
|
[endsect]
|
|
[section Class template `detail::operator_`]
|
|
Instantiations of `detail::operator_<>` are used as the return type of operator expressions involving [link high_level_components.boost_python_operators_hpp.object_self self]. This should be considered an implementation detail and is only documented here as a way of showing how the result of self-expressions match calls to [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel.class_template_class_modifier_fu `class_<>::def()`].
|
|
``
|
|
namespace boost { namespace python { namespace detail
|
|
{
|
|
template <unspecified>
|
|
struct operator_
|
|
{
|
|
};
|
|
}}}
|
|
``
|
|
[endsect]
|
|
[section Object `self`]
|
|
``
|
|
namespace boost { namespace python
|
|
{
|
|
using self_ns::self;
|
|
}}
|
|
``
|
|
[endsect]
|
|
[section Example]
|
|
``
|
|
#include <boost/python/module.hpp>
|
|
#include <boost/python/class.hpp>
|
|
#include <boost/python/operators.hpp>
|
|
#include <boost/operators.hpp>
|
|
|
|
struct number
|
|
: boost::integer_arithmetic<number>
|
|
{
|
|
explicit number(long x_) : x(x_) {}
|
|
operator long() const { return x; }
|
|
|
|
template <class T>
|
|
number& operator+=(T const& rhs)
|
|
{ x += rhs; return *this; }
|
|
|
|
template <class T>
|
|
number& operator-=(T const& rhs)
|
|
{ x -= rhs; return *this; }
|
|
|
|
template <class T>
|
|
number& operator*=(T const& rhs)
|
|
{ x *= rhs; return *this; }
|
|
|
|
template <class T>
|
|
number& operator/=(T const& rhs)
|
|
{ x /= rhs; return *this; }
|
|
|
|
template <class T>
|
|
number& operator%=(T const& rhs)
|
|
{ x %= rhs; return *this; }
|
|
|
|
long x;
|
|
};
|
|
|
|
using namespace boost::python;
|
|
BOOST_PYTHON_MODULE(demo)
|
|
{
|
|
class_<number>("number", init<long>())
|
|
// interoperate with self
|
|
.def(self += self)
|
|
.def(self + self)
|
|
.def(self -= self)
|
|
.def(self - self)
|
|
.def(self *= self)
|
|
.def(self * self)
|
|
.def(self /= self)
|
|
.def(self / self)
|
|
.def(self %= self)
|
|
.def(self % self)
|
|
|
|
// Convert to Python int
|
|
.def(int_(self))
|
|
|
|
// interoperate with long
|
|
.def(self += long())
|
|
.def(self + long())
|
|
.def(long() + self)
|
|
.def(self -= long())
|
|
.def(self - long())
|
|
.def(long() - self)
|
|
.def(self *= long())
|
|
.def(self * long())
|
|
.def(long() * self)
|
|
.def(self /= long())
|
|
.def(self / long())
|
|
.def(long() / self)
|
|
.def(self %= long())
|
|
.def(self % long())
|
|
.def(long() % self)
|
|
;
|
|
}
|
|
``
|
|
[endsect]
|
|
[endsect]
|