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