Chris@16
|
1 // Copyright David Abrahams 2002.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
3 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5 #ifndef OPERATORS_DWA2002530_HPP
|
Chris@16
|
6 # define OPERATORS_DWA2002530_HPP
|
Chris@16
|
7
|
Chris@16
|
8 # include <boost/python/detail/prefix.hpp>
|
Chris@16
|
9
|
Chris@16
|
10 # include <boost/python/def_visitor.hpp>
|
Chris@16
|
11 # include <boost/python/converter/arg_to_python.hpp>
|
Chris@16
|
12 # include <boost/python/detail/operator_id.hpp>
|
Chris@16
|
13 # include <boost/python/detail/not_specified.hpp>
|
Chris@16
|
14 # include <boost/python/back_reference.hpp>
|
Chris@16
|
15 # include <boost/mpl/if.hpp>
|
Chris@16
|
16 # include <boost/mpl/eval_if.hpp>
|
Chris@16
|
17 # include <boost/python/self.hpp>
|
Chris@16
|
18 # include <boost/python/other.hpp>
|
Chris@16
|
19 # include <boost/lexical_cast.hpp>
|
Chris@16
|
20 # include <boost/python/refcount.hpp>
|
Chris@16
|
21 # include <boost/python/detail/unwrap_wrapper.hpp>
|
Chris@16
|
22 # include <string>
|
Chris@16
|
23 # include <complex>
|
Chris@16
|
24
|
Chris@16
|
25 namespace boost { namespace python {
|
Chris@16
|
26
|
Chris@16
|
27 namespace detail
|
Chris@16
|
28 {
|
Chris@16
|
29 // This is essentially the old v1 to_python(). It will be eliminated
|
Chris@16
|
30 // once the public interface for to_python is settled on.
|
Chris@16
|
31 template <class T>
|
Chris@16
|
32 PyObject* convert_result(T const& x)
|
Chris@16
|
33 {
|
Chris@16
|
34 return converter::arg_to_python<T>(x).release();
|
Chris@16
|
35 }
|
Chris@16
|
36
|
Chris@16
|
37 // Operator implementation template declarations. The nested apply
|
Chris@16
|
38 // declaration here keeps MSVC6 happy.
|
Chris@16
|
39 template <operator_id> struct operator_l
|
Chris@16
|
40 {
|
Chris@16
|
41 template <class L, class R> struct apply;
|
Chris@16
|
42 };
|
Chris@16
|
43
|
Chris@16
|
44 template <operator_id> struct operator_r
|
Chris@16
|
45 {
|
Chris@16
|
46 template <class L, class R> struct apply;
|
Chris@16
|
47 };
|
Chris@16
|
48
|
Chris@16
|
49 template <operator_id> struct operator_1
|
Chris@16
|
50 {
|
Chris@16
|
51 template <class T> struct apply;
|
Chris@16
|
52 };
|
Chris@16
|
53
|
Chris@16
|
54 // MSVC6 doesn't want us to do this sort of inheritance on a nested
|
Chris@16
|
55 // class template, so we use this layer of indirection to avoid
|
Chris@16
|
56 // ::template<...> on the nested apply functions below
|
Chris@16
|
57 template <operator_id id, class L, class R>
|
Chris@16
|
58 struct operator_l_inner
|
Chris@16
|
59 : operator_l<id>::template apply<L,R>
|
Chris@16
|
60 {};
|
Chris@16
|
61
|
Chris@16
|
62 template <operator_id id, class L, class R>
|
Chris@16
|
63 struct operator_r_inner
|
Chris@16
|
64 : operator_r<id>::template apply<L,R>
|
Chris@16
|
65 {};
|
Chris@16
|
66
|
Chris@16
|
67 template <operator_id id, class T>
|
Chris@16
|
68 struct operator_1_inner
|
Chris@16
|
69 : operator_1<id>::template apply<T>
|
Chris@16
|
70 {};
|
Chris@16
|
71
|
Chris@16
|
72 // Define three different binary_op templates which take care of
|
Chris@16
|
73 // these cases:
|
Chris@16
|
74 // self op self
|
Chris@16
|
75 // self op R
|
Chris@16
|
76 // L op self
|
Chris@16
|
77 //
|
Chris@16
|
78 // The inner apply metafunction is used to adjust the operator to
|
Chris@16
|
79 // the class type being defined. Inheritance of the outer class is
|
Chris@16
|
80 // simply used to provide convenient access to the operation's
|
Chris@16
|
81 // name().
|
Chris@16
|
82
|
Chris@16
|
83 // self op self
|
Chris@16
|
84 template <operator_id id>
|
Chris@16
|
85 struct binary_op : operator_l<id>
|
Chris@16
|
86 {
|
Chris@16
|
87 template <class T>
|
Chris@16
|
88 struct apply : operator_l_inner<id,T,T>
|
Chris@16
|
89 {
|
Chris@16
|
90 };
|
Chris@16
|
91 };
|
Chris@16
|
92
|
Chris@16
|
93 // self op R
|
Chris@16
|
94 template <operator_id id, class R>
|
Chris@16
|
95 struct binary_op_l : operator_l<id>
|
Chris@16
|
96 {
|
Chris@16
|
97 template <class T>
|
Chris@16
|
98 struct apply : operator_l_inner<id,T,R>
|
Chris@16
|
99 {
|
Chris@16
|
100 };
|
Chris@16
|
101 };
|
Chris@16
|
102
|
Chris@16
|
103 // L op self
|
Chris@16
|
104 template <operator_id id, class L>
|
Chris@16
|
105 struct binary_op_r : operator_r<id>
|
Chris@16
|
106 {
|
Chris@16
|
107 template <class T>
|
Chris@16
|
108 struct apply : operator_r_inner<id,L,T>
|
Chris@16
|
109 {
|
Chris@16
|
110 };
|
Chris@16
|
111 };
|
Chris@16
|
112
|
Chris@16
|
113 template <operator_id id>
|
Chris@16
|
114 struct unary_op : operator_1<id>
|
Chris@16
|
115 {
|
Chris@16
|
116 template <class T>
|
Chris@16
|
117 struct apply : operator_1_inner<id,T>
|
Chris@16
|
118 {
|
Chris@16
|
119 };
|
Chris@16
|
120 };
|
Chris@16
|
121
|
Chris@16
|
122 // This type is what actually gets returned from operators used on
|
Chris@16
|
123 // self_t
|
Chris@16
|
124 template <operator_id id, class L = not_specified, class R = not_specified>
|
Chris@16
|
125 struct operator_
|
Chris@16
|
126 : def_visitor<operator_<id,L,R> >
|
Chris@16
|
127 {
|
Chris@16
|
128 private:
|
Chris@16
|
129 template <class ClassT>
|
Chris@16
|
130 void visit(ClassT& cl) const
|
Chris@16
|
131 {
|
Chris@16
|
132 typedef typename mpl::eval_if<
|
Chris@16
|
133 is_same<L,self_t>
|
Chris@16
|
134 , mpl::if_<
|
Chris@16
|
135 is_same<R,self_t>
|
Chris@16
|
136 , binary_op<id>
|
Chris@16
|
137 , binary_op_l<
|
Chris@16
|
138 id
|
Chris@16
|
139 , BOOST_DEDUCED_TYPENAME unwrap_other<R>::type
|
Chris@16
|
140 >
|
Chris@16
|
141 >
|
Chris@16
|
142 , mpl::if_<
|
Chris@16
|
143 is_same<L,not_specified>
|
Chris@16
|
144 , unary_op<id>
|
Chris@16
|
145 , binary_op_r<
|
Chris@16
|
146 id
|
Chris@16
|
147 , BOOST_DEDUCED_TYPENAME unwrap_other<L>::type
|
Chris@16
|
148 >
|
Chris@16
|
149 >
|
Chris@16
|
150 >::type generator;
|
Chris@16
|
151
|
Chris@16
|
152 cl.def(
|
Chris@16
|
153 generator::name()
|
Chris@16
|
154 , &generator::template apply<
|
Chris@16
|
155 BOOST_DEDUCED_TYPENAME ClassT::wrapped_type
|
Chris@16
|
156 >::execute
|
Chris@16
|
157 );
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 friend class python::def_visitor_access;
|
Chris@16
|
161 };
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 # define BOOST_PYTHON_BINARY_OPERATION(id, rid, expr) \
|
Chris@16
|
165 namespace detail \
|
Chris@16
|
166 { \
|
Chris@16
|
167 template <> \
|
Chris@16
|
168 struct operator_l<op_##id> \
|
Chris@16
|
169 { \
|
Chris@16
|
170 template <class L, class R> \
|
Chris@16
|
171 struct apply \
|
Chris@16
|
172 { \
|
Chris@16
|
173 typedef typename unwrap_wrapper_<L>::type lhs; \
|
Chris@16
|
174 typedef typename unwrap_wrapper_<R>::type rhs; \
|
Chris@16
|
175 static PyObject* execute(lhs& l, rhs const& r) \
|
Chris@16
|
176 { \
|
Chris@16
|
177 return detail::convert_result(expr); \
|
Chris@16
|
178 } \
|
Chris@16
|
179 }; \
|
Chris@16
|
180 static char const* name() { return "__" #id "__"; } \
|
Chris@16
|
181 }; \
|
Chris@16
|
182 \
|
Chris@16
|
183 template <> \
|
Chris@16
|
184 struct operator_r<op_##id> \
|
Chris@16
|
185 { \
|
Chris@16
|
186 template <class L, class R> \
|
Chris@16
|
187 struct apply \
|
Chris@16
|
188 { \
|
Chris@16
|
189 typedef typename unwrap_wrapper_<L>::type lhs; \
|
Chris@16
|
190 typedef typename unwrap_wrapper_<R>::type rhs; \
|
Chris@16
|
191 static PyObject* execute(rhs& r, lhs const& l) \
|
Chris@16
|
192 { \
|
Chris@16
|
193 return detail::convert_result(expr); \
|
Chris@16
|
194 } \
|
Chris@16
|
195 }; \
|
Chris@16
|
196 static char const* name() { return "__" #rid "__"; } \
|
Chris@16
|
197 }; \
|
Chris@16
|
198 }
|
Chris@16
|
199
|
Chris@16
|
200 # define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op) \
|
Chris@16
|
201 BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r) \
|
Chris@16
|
202 namespace self_ns \
|
Chris@16
|
203 { \
|
Chris@16
|
204 template <class L, class R> \
|
Chris@16
|
205 inline detail::operator_<detail::op_##id,L,R> \
|
Chris@16
|
206 operator op(L const&, R const&) \
|
Chris@16
|
207 { \
|
Chris@16
|
208 return detail::operator_<detail::op_##id,L,R>(); \
|
Chris@16
|
209 } \
|
Chris@16
|
210 }
|
Chris@16
|
211
|
Chris@16
|
212 BOOST_PYTHON_BINARY_OPERATOR(add, radd, +)
|
Chris@16
|
213 BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -)
|
Chris@16
|
214 BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *)
|
Chris@16
|
215 #if PY_VERSION_HEX >= 0x03000000
|
Chris@16
|
216 BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /)
|
Chris@16
|
217 #else
|
Chris@16
|
218 BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
|
Chris@16
|
219 #endif
|
Chris@16
|
220 BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
|
Chris@16
|
221 BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
|
Chris@16
|
222 BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
|
Chris@16
|
223 BOOST_PYTHON_BINARY_OPERATOR(and, rand, &)
|
Chris@16
|
224 BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^)
|
Chris@16
|
225 BOOST_PYTHON_BINARY_OPERATOR(or, ror, |)
|
Chris@16
|
226 BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >)
|
Chris@16
|
227 BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=)
|
Chris@16
|
228 BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <)
|
Chris@16
|
229 BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=)
|
Chris@16
|
230 BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==)
|
Chris@16
|
231 BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=)
|
Chris@16
|
232 # undef BOOST_PYTHON_BINARY_OPERATOR
|
Chris@16
|
233
|
Chris@16
|
234 // pow isn't an operator in C++; handle it specially.
|
Chris@16
|
235 BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r))
|
Chris@16
|
236 # undef BOOST_PYTHON_BINARY_OPERATION
|
Chris@16
|
237
|
Chris@16
|
238 namespace self_ns
|
Chris@16
|
239 {
|
Chris@16
|
240 # ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
Chris@16
|
241 template <class L, class R>
|
Chris@16
|
242 inline detail::operator_<detail::op_pow,L,R>
|
Chris@16
|
243 pow(L const&, R const&)
|
Chris@16
|
244 {
|
Chris@16
|
245 return detail::operator_<detail::op_pow,L,R>();
|
Chris@16
|
246 }
|
Chris@16
|
247 # else
|
Chris@16
|
248 // When there's no argument-dependent lookup, we need these
|
Chris@16
|
249 // overloads to handle the case when everything is imported into the
|
Chris@16
|
250 // global namespace. Note that the plain overload below does /not/
|
Chris@16
|
251 // take const& arguments. This is needed by MSVC6 at least, or it
|
Chris@16
|
252 // complains of ambiguities, since there's no partial ordering.
|
Chris@16
|
253 inline detail::operator_<detail::op_pow,self_t,self_t>
|
Chris@16
|
254 pow(self_t, self_t)
|
Chris@16
|
255 {
|
Chris@16
|
256 return detail::operator_<detail::op_pow,self_t,self_t>();
|
Chris@16
|
257 }
|
Chris@16
|
258 template <class R>
|
Chris@16
|
259 inline detail::operator_<detail::op_pow,self_t,R>
|
Chris@16
|
260 pow(self_t const&, R const&)
|
Chris@16
|
261 {
|
Chris@16
|
262 return detail::operator_<detail::op_pow,self_t,R>();
|
Chris@16
|
263 }
|
Chris@16
|
264 template <class L>
|
Chris@16
|
265 inline detail::operator_<detail::op_pow,L,self_t>
|
Chris@16
|
266 pow(L const&, self_t const&)
|
Chris@16
|
267 {
|
Chris@16
|
268 return detail::operator_<detail::op_pow,L,self_t>();
|
Chris@16
|
269 }
|
Chris@16
|
270 # endif
|
Chris@16
|
271 }
|
Chris@16
|
272
|
Chris@16
|
273
|
Chris@16
|
274 # define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \
|
Chris@16
|
275 namespace detail \
|
Chris@16
|
276 { \
|
Chris@16
|
277 template <> \
|
Chris@16
|
278 struct operator_l<op_##id> \
|
Chris@16
|
279 { \
|
Chris@16
|
280 template <class L, class R> \
|
Chris@16
|
281 struct apply \
|
Chris@16
|
282 { \
|
Chris@16
|
283 typedef typename unwrap_wrapper_<L>::type lhs; \
|
Chris@16
|
284 typedef typename unwrap_wrapper_<R>::type rhs; \
|
Chris@16
|
285 static PyObject* \
|
Chris@16
|
286 execute(back_reference<lhs&> l, rhs const& r) \
|
Chris@16
|
287 { \
|
Chris@16
|
288 l.get() op r; \
|
Chris@16
|
289 return python::incref(l.source().ptr()); \
|
Chris@16
|
290 } \
|
Chris@16
|
291 }; \
|
Chris@16
|
292 static char const* name() { return "__" #id "__"; } \
|
Chris@16
|
293 }; \
|
Chris@16
|
294 } \
|
Chris@16
|
295 namespace self_ns \
|
Chris@16
|
296 { \
|
Chris@16
|
297 template <class R> \
|
Chris@16
|
298 inline detail::operator_<detail::op_##id,self_t,R> \
|
Chris@16
|
299 operator op(self_t const&, R const&) \
|
Chris@16
|
300 { \
|
Chris@16
|
301 return detail::operator_<detail::op_##id,self_t,R>(); \
|
Chris@16
|
302 } \
|
Chris@16
|
303 }
|
Chris@16
|
304
|
Chris@16
|
305 BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=)
|
Chris@16
|
306 BOOST_PYTHON_INPLACE_OPERATOR(isub,-=)
|
Chris@16
|
307 BOOST_PYTHON_INPLACE_OPERATOR(imul,*=)
|
Chris@16
|
308 BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=)
|
Chris@16
|
309 BOOST_PYTHON_INPLACE_OPERATOR(imod,%=)
|
Chris@16
|
310 BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=)
|
Chris@16
|
311 BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=)
|
Chris@16
|
312 BOOST_PYTHON_INPLACE_OPERATOR(iand,&=)
|
Chris@16
|
313 BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=)
|
Chris@16
|
314 BOOST_PYTHON_INPLACE_OPERATOR(ior,|=)
|
Chris@16
|
315
|
Chris@16
|
316 # define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name) \
|
Chris@16
|
317 namespace detail \
|
Chris@16
|
318 { \
|
Chris@16
|
319 template <> \
|
Chris@16
|
320 struct operator_1<op_##id> \
|
Chris@16
|
321 { \
|
Chris@16
|
322 template <class T> \
|
Chris@16
|
323 struct apply \
|
Chris@16
|
324 { \
|
Chris@16
|
325 typedef typename unwrap_wrapper_<T>::type self_t; \
|
Chris@16
|
326 static PyObject* execute(self_t& x) \
|
Chris@16
|
327 { \
|
Chris@16
|
328 return detail::convert_result(op(x)); \
|
Chris@16
|
329 } \
|
Chris@16
|
330 }; \
|
Chris@16
|
331 static char const* name() { return "__" #id "__"; } \
|
Chris@16
|
332 }; \
|
Chris@16
|
333 } \
|
Chris@16
|
334 namespace self_ns \
|
Chris@16
|
335 { \
|
Chris@16
|
336 inline detail::operator_<detail::op_##id> \
|
Chris@16
|
337 func_name(self_t const&) \
|
Chris@16
|
338 { \
|
Chris@16
|
339 return detail::operator_<detail::op_##id>(); \
|
Chris@16
|
340 } \
|
Chris@16
|
341 }
|
Chris@16
|
342 # undef BOOST_PYTHON_INPLACE_OPERATOR
|
Chris@16
|
343
|
Chris@16
|
344 BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
|
Chris@16
|
345 BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
|
Chris@16
|
346 BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
|
Chris@16
|
347 BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
|
Chris@16
|
348 #if PY_VERSION_HEX >= 0x03000000
|
Chris@16
|
349 BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!)
|
Chris@16
|
350 #else
|
Chris@16
|
351 BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
|
Chris@16
|
352 #endif
|
Chris@16
|
353 BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
|
Chris@16
|
354 BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
|
Chris@16
|
355 BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
|
Chris@16
|
356 BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
|
Chris@16
|
357 BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
|
Chris@16
|
358 BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr)
|
Chris@16
|
359 # undef BOOST_PYTHON_UNARY_OPERATOR
|
Chris@16
|
360
|
Chris@16
|
361 }} // namespace boost::python
|
Chris@16
|
362
|
Chris@16
|
363 # ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
Chris@16
|
364 using boost::python::self_ns::abs;
|
Chris@16
|
365 using boost::python::self_ns::int_;
|
Chris@16
|
366 using boost::python::self_ns::long_;
|
Chris@16
|
367 using boost::python::self_ns::float_;
|
Chris@16
|
368 using boost::python::self_ns::complex_;
|
Chris@16
|
369 using boost::python::self_ns::str;
|
Chris@16
|
370 using boost::python::self_ns::repr;
|
Chris@16
|
371 using boost::python::self_ns::pow;
|
Chris@16
|
372 # endif
|
Chris@16
|
373
|
Chris@16
|
374 #endif // OPERATORS_DWA2002530_HPP
|