Boost.Python - <boost/python/operators.hpp>

###  | # Boost.Python ## Header <boost/python/operators.hpp>

## Contents

Introduction
Classes
  Class `self_ns::self_t`
    Class `self_t` synopsis
    Class `self_t` inplace operators
    Class `self_t` comparison functions
    Class `self_t` non-member operations
    Class `self_t` unary operations
    Class `self_t` value operations
  Class template `other`
    Class `other` synopsis
  Class template `operator_`
    Class `operator_` synopsis
Objects
  self
Examples

## Introduction

`<boost/python/operators.hpp>` provides types and functions for automatically generating Python special methods from the corresponding C++ constructs. Most of these constructs are operator expressions, hence the name. To use the facility, substitute the `self` object for an object of the class type being wrapped in the expression to be exposed, and pass the result to class_<>::def(). Much of what is exposed in this header should be considered part of the implementation, so is not documented in detail here.

## Classes

### Class `self_ns::self_t`

`self_ns::self_t` is the actual type of the `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.

#### Class `self_ns::self_t` synopsis

    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);

    }}};

The tables below describe the methods generated when the results of the expressions described are passed as arguments to class_<>::def(). `x` is an object of the class type being wrapped.

#### Class `self_t` inplace operators

In the table below, If `r` is an object of type `other<T>`, `y` is an object of type `T`; otherwise, `y` is an object of the same type as `r`.

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`

#### Class `self_t` comparison functions

In the tables below, if `r` is of type `self_t`, `y` is an object of the same type as `x`;
if `l` or `r` is an object of type `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 `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 reflection rules for rich comparison operators, and are only used when the corresponding operation is not defined as a method of the `y` object.

C++ Expression | Python Method Name | C++ Implementation | Python Expressions (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`

#### Class `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 here.

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` | `__mul__` | `x * y`
`l * self` | `__rmul__` | `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__` | `pow(x, y)`
`pow(l, self)` | `__rpow__` | `pow(y, x)`

#### Class `self_t` unary operations

C++ Expression | Python Method Name | C++ Implementation
--- | --- | ---
`-self` | `__neg__` | `-x`
`+self` | `__pos__` | `+x`
`~self` | `__invert__` | `~x`
`not self` or `!self` | `__nonzero__` | `!!x`

#### Class `self_t` value operations

C++ Expression | Python Method Name | C++ Implementation
--- | --- | ---
`int_(self)` | `__int__` | `long(x)`
`long_` | `__long__` | `PyLong_FromLong(x)`
`float_` | `__float__` | `double(x)`
`complex_` | `__complex__` | `std::complex<double>(x)`
`str` | `__str__` | `lexical_cast<std::string>(x)`

### Class Template `other`

Instances of `other<T>` can be used in operator expressions with 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.

#### Class Template other synopsis

    namespace boost { namespace python
    {
      template <class T>
      struct other
      {
      };
    }}

### Class Template `detail::operator_`

Instantiations of `detail::operator_<>` are used as the return type of operator expressions involving `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 class_<>::def().

#### Class Template `detail::operator_` synopsis

    namespace boost { namespace python { namespace detail
    {
      template <unspecified>
      struct operator_
      {
      };
    }}}

## Objects

`self`

    namespace boost { namespace python
    {
      using self_ns::self;
    }}

## 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>
    {
       number(long x_) : x(x_) {}
       operator long() const { return x; }

       number& operator+=(number const& rhs)
          { x += rhs }
       number& operator-=(number const& rhs);
          { x -= rhs }
       number& operator*=(number const& rhs)
          { x *= rhs }
       number& operator/=(number const& rhs);
          { x /= rhs }
       number& operator%=(number const& rhs);
          { x %= rhs }

       long x;
    };

    using namespace boost::python;
    BOOST_PYTHON_MODULE(demo)
    {
       class_<number>("number")
          // 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)
          ;
    }

Revised 3 October, 2003

© Copyright Dave Abrahams 2002. All Rights Reserved.