boost/python/operators.hpp
はじめに
<boost/python/operators.hpp>
は、Python の特殊メソッドを C++ の対応する構造から自動的に生成する型と関数を提供する。これらの構造の大半は演算子式であり、ヘッダの名前はそこから来ている。この機能を使用するには、エクスポートする式中でラップするクラス型のオブジェクトを self
オブジェクトで置き換え、その結果を class_<>::def
へ渡す。このヘッダがエクスポートするものの大半は実装部分と考えるべきであり、本稿では詳細について記述しない。
クラス
self_ns::self_t
クラス
-
class self_ns::self_t
self_ns::self_t
はself
オブジェクトの実際の型である。ライブラリはself_t
を自身の名前空間self_ns
内に分離し、他の文脈で引数依存の探索により一般化された演算子テンプレートが発見されるのを防ぐ。ユーザが直接self_t
に触れることはないため、これは実装の詳細と考えるべきである。
self_ns::self_t
クラスの概要
namespace boost { namespace python { namespace self_ns {
{
unspecified-type-declaration self_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);
template <class T> operator_<unspecified> operator|=(self_t, T);
// 比較演算子
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> 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&);
// 単項演算子
operator_<unspecified> operator-(self_t);
operator_<unspecified> operator+(self_t);
operator_<unspecified> operator~(self_t);
operator_<unspecified> operator!(self_t);
// 値操作
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);
}}};
各式の結果を class_<>::def
の引数として渡したときに生成されるメソッドを以下の表に挙げる。x
はラップするクラス型のオブジェクトである。
self_ns::self_t
クラスの複合演算子
下表において r
が other
型のオブジェクトの場合、y
は型 T
のオブジェクトである。それ以外の場合、y
は r
と同じ型のオブジェクトである。
C++ の式 |
Python のメソッド名 |
C++ の実装 |
---|---|---|
self += r |
|
x += y |
self -= r |
|
x -= y |
self *= r |
|
x *= y |
self /= r |
|
x /= y |
self %= r |
|
x %= y |
self >>= r |
|
x >>= y |
self <<= r |
|
x <<= y |
self &= r |
|
x &= y |
self ^= r |
|
x ^= y |
self |= r |
|
x |= y |
self_ns::self_t
クラスの比較関数
下表において r
が self_t
型の場合、y
は x
と同じ型のオブジェクトである。l
か r
が other<T>
型のオブジェクトの場合、y
は型 T
のオブジェクトである。それ以外の場合、y
は l
か r
と同じ型のオブジェクトであり、l
は self_t
型以外である。
「Python の式」の列は、x
および y
の型へ変換可能なオブジェクトについて Python がサポートする式を表す。2 番目の演算は Python の高水準比較演算子の反射則(可換則)により生じるもので、対応する演算が y
オブジェクトのメソッドとして定義されない場合のみ使用される。
C++ の式 |
Python のメソッド名 |
C++ の実装 |
Python の式(1 番目、2 番目) |
---|---|---|---|
self == r |
|
x == y |
|
l == self |
|
y == x |
|
self != r |
|
x != y |
|
l != self |
|
y != x |
|
self < r |
|
x < y |
|
l < self |
|
y < x |
|
self > r |
|
x > y |
|
l > self |
|
y > x |
|
self <= r |
|
x <= y |
|
l <= self |
|
y <= x |
|
self >= r |
|
x >= y |
|
l >= self |
|
y >= x |
|
self_ns::self_t
クラスの非メンバ演算子
ここで述べられているように、以下の名前が「__r
」で始まる演算は左オペランドが与えられた演算をサポートしない場合のみ呼び出される。
C++ の式 |
Python のメソッド名 |
C++ の実装 |
---|---|---|
self + r |
|
x + y |
l + self |
|
y + x |
self - r |
|
x - y |
l - self |
|
y - x |
self * r |
|
x * y |
l * self |
|
y * x |
self / r |
|
x / y |
l / self |
|
y / x |
self % r |
|
x % y |
l % self |
|
y % x |
self >> r |
|
x >> y |
l >> self |
|
y >> x |
self << r |
|
x << y |
l << self |
|
y << x |
self & r |
|
x & y |
l & self |
|
y & x |
self ^ r |
|
x ^ y |
l ^ self |
|
y ^ x |
self | r |
|
x | y |
l | self |
|
y | x |
pow(self, r) |
|
pow(x, y) |
pow(l, self) |
|
pow(y, x) |
self_ns::self_t
クラスの単項演算子
C++ の式 |
Python のメソッド名 |
C++ の実装 |
---|---|---|
-self |
|
-x |
+self |
|
+x |
~self |
|
~x |
|
!!x |
self_ns::self_t
クラスの値演算
C++ の式 |
Python のメソッド |
C++ の実装1 |
---|---|---|
int_(self) |
|
long(x) |
|
PyLong_FromLong(x) |
|
float_ |
|
double(x) |
complex_ |
|
std::complex<double>(x) |
|
lexical_cast<std::string>(x) |
|
repr |
|
lexical_cast<std::string>(x) |
other
クラステンプレート
-
template<class T>
struct other other<T>
のインスタンスはself
とともに演算子式中で使用し、結果は同じ式のother<T>
をT
オブジェクトで置き換えたものと等価である。T
オブジェクトの構築が高価で避けたい場合、コンストラクタが利用できない場合、または単純にコードを明確にする場合にother<T>
を使用するとよい。
other
クラステンプレートの概要
namespace boost { namespace python
template <class T>
struct other
{
};
}
detail::operator_
クラステンプレート
-
template<unspecified>
struct detail::operator_ detail::operator_<>
のインスタンス化は、self
を含む演算子式の戻り値型として使用する。これは実装の詳細として考えるべきであり、self
式の結果がどのようにclass_<>::def
呼び出しとマッチするか見るためとしてのみ、ここに記載する。
detail::operator_
クラステンプレートの概要
namespace boost { namespace python { namespace detail
{
template <unspecified>
struct operator_
{
};
}}}
オブジェクト
self
例2
#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>())
// 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)
// Python の int への変換
.def(int_(self))
// 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)
;
}