]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [section boost/python/operators.hpp] |
2 | [section Introduction] | |
3 | <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. | |
4 | [endsect] | |
5 | [section Class `self_ns::self_t`] | |
6 | `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. | |
7 | `` | |
8 | namespace boost { namespace python { namespace self_ns { | |
9 | { | |
10 | unspecified-type-declaration self_t; | |
11 | ||
12 | // inplace operators | |
13 | template <class T> operator_<unspecified> operator+=(self_t, T); | |
14 | template <class T> operator_<unspecified> operator-=(self_t, T); | |
15 | template <class T> operator_<unspecified> operator*=(self_t, T); | |
16 | template <class T> operator_<unspecified> operator/=(self_t, T); | |
17 | template <class T> operator_<unspecified> operator%=(self_t, T); | |
18 | template <class T> operator_<unspecified> operator>>=(self_t, T); | |
19 | template <class T> operator_<unspecified> operator<<=(self_t, T); | |
20 | template <class T> operator_<unspecified> operator&=(self_t, T); | |
21 | template <class T> operator_<unspecified> operator^=(self_t, T); | |
22 | template <class T> operator_<unspecified> operator|=(self_t, T); | |
23 | ||
24 | // comparisons | |
25 | template <class L, class R> operator_<unspecified> operator==(L const&, R const&); | |
26 | template <class L, class R> operator_<unspecified> operator!=(L const&, R const&); | |
27 | template <class L, class R> operator_<unspecified> operator<(L const&, R const&); | |
28 | template <class L, class R> operator_<unspecified> operator>(L const&, R const&); | |
29 | template <class L, class R> operator_<unspecified> operator<=(L const&, R const&); | |
30 | template <class L, class R> operator_<unspecified> operator>=(L const&, R const&); | |
31 | ||
32 | // non-member operations | |
33 | template <class L, class R> operator_<unspecified> operator+(L const&, R const&); | |
34 | template <class L, class R> operator_<unspecified> operator-(L const&, R const&); | |
35 | template <class L, class R> operator_<unspecified> operator*(L const&, R const&); | |
36 | template <class L, class R> operator_<unspecified> operator/(L const&, R const&); | |
37 | template <class L, class R> operator_<unspecified> operator%(L const&, R const&); | |
38 | template <class L, class R> operator_<unspecified> operator>>(L const&, R const&); | |
39 | template <class L, class R> operator_<unspecified> operator<<(L const&, R const&); | |
40 | template <class L, class R> operator_<unspecified> operator&(L const&, R const&); | |
41 | template <class L, class R> operator_<unspecified> operator^(L const&, R const&); | |
42 | template <class L, class R> operator_<unspecified> operator|(L const&, R const&); | |
43 | template <class L, class R> operator_<unspecified> pow(L const&, R const&); | |
44 | ||
45 | // unary operations | |
46 | operator_<unspecified> operator-(self_t); | |
47 | operator_<unspecified> operator+(self_t); | |
48 | operator_<unspecified> operator~(self_t); | |
49 | operator_<unspecified> operator!(self_t); | |
50 | ||
51 | // value operations | |
52 | operator_<unspecified> int_(self_t); | |
53 | operator_<unspecified> long_(self_t); | |
54 | operator_<unspecified> float_(self_t); | |
55 | operator_<unspecified> complex_(self_t); | |
56 | operator_<unspecified> str(self_t); | |
57 | ||
58 | operator_<unspecified> repr(self_t); | |
59 | }}}; | |
60 | `` | |
61 | 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. | |
62 | [section `self_t` inplace operators] | |
63 | 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`. | |
64 | [table | |
65 | [[C++ Expression][Python Method Name][C++ Implementation]] | |
66 | [[`self += r`][`__iadd__`][`x += y`]] | |
67 | [[`self -= r`][`__isub__`][`x -= y`]] | |
68 | [[`self *= r`][`__imul__`][`x *= y`]] | |
69 | [[`self /= r`][`__idiv__`][`x /= y`]] | |
70 | [[`self %= r`][`__imod__`][`x %= y`]] | |
71 | [[`self >>= r`][`__irshift__`][`x >>= y`]] | |
72 | [[`self <<= r`][`__ilshift__`][`x <<= y`]] | |
73 | [[`self &= r`][`__iand__`][`x &= y`]] | |
74 | [[`self ^= r`][`__ixor__`][`x ^= y`]] | |
75 | [[`self |= r`][`__ior__`][`x |= y`]] | |
76 | ] | |
77 | [endsect] | |
78 | [section `self_t` comparison functions] | |
79 | 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`; | |
80 | 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`; | |
81 | otherwise, `y` is an object of the same type as `l` or `r`. | |
82 | `l` is never of type [link high_level_components.boost_python_operators_hpp.class_self_ns_self_t self_t]. | |
83 | ||
84 | 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. | |
85 | [table | |
86 | [[C++ Expression][Python Method Name][C++ Implementation][Python Expression (primary, secondary)]] | |
87 | [[`self == r`][`__eq__`][`x == y`][`x == y`, `y == x`]] | |
88 | [[`l == self`][`__eq__`][`y == x`][`y == x`, `x == y`]] | |
89 | [[`self != r`][`__nq__`][`x != y`][`x != y`, `y != x`]] | |
90 | [[`l != self`][`__nq__`][`y != x`][`y != x`, `x != y`]] | |
91 | [[`self < r`][`__lt__`][`x < y`][`x < y`, `y > x`]] | |
92 | [[`l < self`][`__gt__`][`y < x`][`y > x`, `x < y`]] | |
93 | [[`self > r`][`__gt__`][`x > y`][`x > y`, `y < x`]] | |
94 | [[`l > self`][`__lt__`][`y > x`][`y < x`, `x > y`]] | |
95 | [[`self <= r`][`__le__`][`x <= y`][`x <= y`, `y >= x`]] | |
96 | [[`l <= self`][`__ge__`][`y <= x`][`y >= x`, `x <= y`]] | |
97 | [[`self >= r`][`__ge__`][`x >= y`][`x >= y`, `y <= x`]] | |
98 | [[`l <= self`][`__le__`][`y >= x`][`y <= x`, `x >= y`]] | |
99 | ] | |
100 | [endsect] | |
101 | [section `self_t` non-member operations] | |
102 | 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]. | |
103 | [table | |
104 | [[C++ Expression][Python Method Name][C++ Implementation]] | |
105 | [[`self + r`][`__add__`][`x + y`]] | |
106 | [[`l + self`][`__radd__`][`y + x`]] | |
107 | [[`self - r`][`__sub__`][`x - y`]] | |
108 | [[`l - self`][`__rsub__`][`y - x`]] | |
109 | [[`self * r`][`__mult__`][`x * y`]] | |
110 | [[`l * self`][`__rmult__`][`y * x`]] | |
111 | [[`self / r`][`__div__`][`x / y`]] | |
112 | [[`l / self`][`__rdiv__`][`y / x`]] | |
113 | [[`self % r`][`__mod__`][`x % y`]] | |
114 | [[`l % self`][`__rmod__`][`y % x`]] | |
115 | [[`self >> r`][`__rshift__`][`x >> y`]] | |
116 | [[`l >> self`][`__rrshift__`][`y >> x`]] | |
117 | [[`self << r`][`__lshift__`][`x << y`]] | |
118 | [[`l << self`][`__rlshift__`][`y << x`]] | |
119 | [[`self & r`][`__and__`][`x & y`]] | |
120 | [[`l & self`][`__rand__`][`y & x`]] | |
121 | [[`self ^ r`][`__xor__`][`x ^ y`]] | |
122 | [[`l ^ self`][`__rxor__`][`y ^ x`]] | |
123 | [[`self | r`][`__or__`][`x | y`]] | |
124 | [[`l | self`][`__ror__`][`y | x`]] | |
125 | [[`pow(self, r)`][`__pow__`][`x ** y`]] | |
126 | [[`pow(l, self)`][`__rpow__`][`y ** x`]] | |
127 | ] | |
128 | [endsect] | |
129 | [section `self_t` unary operations] | |
130 | [table | |
131 | [[C++ Expression][Python Method Name][C++ Implementation]] | |
132 | [[`-self`][`__neg__`][`-x`]] | |
133 | [[`+self`][`__pos__`][`+x`]] | |
134 | [[`~self`][`__invert__`][`~x`]] | |
135 | [[`not self` or `!self`][`__nonzero__`][`!!x`]] | |
136 | ] | |
137 | [endsect] | |
138 | [section `self_t` value operations] | |
139 | [table | |
140 | [[C++ Expression][Python Method Name][C++ Implementation]] | |
141 | [[`int_(self)`][`__int__`][`long(x)`]] | |
142 | [[`long_(self)`][`__long__`][`PyLong_FromLong(x)`]] | |
143 | [[`float_(self)`][`__float__`][`double(x)`]] | |
144 | [[`complex_(self)`][`__complex__`][`std::complex<double>(x)`]] | |
145 | [[`str(self)`][`__str__`][`lexical_cast<std::string>(x)`]] | |
146 | [[`repr(self)`][`__repr__`][`lexical_cast<std::string>(x)`]] | |
147 | ] | |
148 | [endsect] | |
149 | [endsect] | |
150 | [section Class template `other`] | |
151 | 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. | |
152 | `` | |
153 | namespace boost { namespace python | |
154 | { | |
155 | template <class T> | |
156 | struct other | |
157 | { | |
158 | }; | |
159 | }} | |
160 | `` | |
161 | [endsect] | |
162 | [section Class template `detail::operator_`] | |
163 | 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()`]. | |
164 | `` | |
165 | namespace boost { namespace python { namespace detail | |
166 | { | |
167 | template <unspecified> | |
168 | struct operator_ | |
169 | { | |
170 | }; | |
171 | }}} | |
172 | `` | |
173 | [endsect] | |
174 | [section Object `self`] | |
175 | `` | |
176 | namespace boost { namespace python | |
177 | { | |
178 | using self_ns::self; | |
179 | }} | |
180 | `` | |
181 | [endsect] | |
182 | [section Example] | |
183 | `` | |
184 | #include <boost/python/module.hpp> | |
185 | #include <boost/python/class.hpp> | |
186 | #include <boost/python/operators.hpp> | |
187 | #include <boost/operators.hpp> | |
188 | ||
189 | struct number | |
190 | : boost::integer_arithmetic<number> | |
191 | { | |
192 | explicit number(long x_) : x(x_) {} | |
193 | operator long() const { return x; } | |
194 | ||
195 | template <class T> | |
196 | number& operator+=(T const& rhs) | |
197 | { x += rhs; return *this; } | |
198 | ||
199 | template <class T> | |
200 | number& operator-=(T const& rhs) | |
201 | { x -= rhs; return *this; } | |
202 | ||
203 | template <class T> | |
204 | number& operator*=(T const& rhs) | |
205 | { x *= rhs; return *this; } | |
206 | ||
207 | template <class T> | |
208 | number& operator/=(T const& rhs) | |
209 | { x /= rhs; return *this; } | |
210 | ||
211 | template <class T> | |
212 | number& operator%=(T const& rhs) | |
213 | { x %= rhs; return *this; } | |
214 | ||
215 | long x; | |
216 | }; | |
217 | ||
218 | using namespace boost::python; | |
219 | BOOST_PYTHON_MODULE(demo) | |
220 | { | |
221 | class_<number>("number", init<long>()) | |
222 | // interoperate with self | |
223 | .def(self += self) | |
224 | .def(self + self) | |
225 | .def(self -= self) | |
226 | .def(self - self) | |
227 | .def(self *= self) | |
228 | .def(self * self) | |
229 | .def(self /= self) | |
230 | .def(self / self) | |
231 | .def(self %= self) | |
232 | .def(self % self) | |
233 | ||
234 | // Convert to Python int | |
235 | .def(int_(self)) | |
236 | ||
237 | // interoperate with long | |
238 | .def(self += long()) | |
239 | .def(self + long()) | |
240 | .def(long() + self) | |
241 | .def(self -= long()) | |
242 | .def(self - long()) | |
243 | .def(long() - self) | |
244 | .def(self *= long()) | |
245 | .def(self * long()) | |
246 | .def(long() * self) | |
247 | .def(self /= long()) | |
248 | .def(self / long()) | |
249 | .def(long() / self) | |
250 | .def(self %= long()) | |
251 | .def(self % long()) | |
252 | .def(long() % self) | |
253 | ; | |
254 | } | |
255 | `` | |
256 | [endsect] | |
257 | [endsect] |