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
25namespace boost { namespace python {
26
27namespace 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) \
165namespace 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) \
201BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r) \
202namespace 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
212BOOST_PYTHON_BINARY_OPERATOR(add, radd, +)
213BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -)
214BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *)
215#if PY_VERSION_HEX >= 0x03000000
216 BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /)
217#else
218 BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
219#endif
220BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
221BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
222BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
223BOOST_PYTHON_BINARY_OPERATOR(and, rand, &)
224BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^)
225BOOST_PYTHON_BINARY_OPERATOR(or, ror, |)
226BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >)
227BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=)
228BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <)
229BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=)
230BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==)
231BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=)
232# undef BOOST_PYTHON_BINARY_OPERATOR
233
234// pow isn't an operator in C++; handle it specially.
235BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r))
236# undef BOOST_PYTHON_BINARY_OPERATION
237
238namespace self_ns
239{
240# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
241 template <class L, class R>
242 inline detail::operator_<detail::op_pow,L,R>
243 pow(L const&, R const&)
244 {
245 return detail::operator_<detail::op_pow,L,R>();
246 }
247# else
248 // When there's no argument-dependent lookup, we need these
249 // overloads to handle the case when everything is imported into the
250 // global namespace. Note that the plain overload below does /not/
251 // take const& arguments. This is needed by MSVC6 at least, or it
252 // complains of ambiguities, since there's no partial ordering.
253 inline detail::operator_<detail::op_pow,self_t,self_t>
254 pow(self_t, self_t)
255 {
256 return detail::operator_<detail::op_pow,self_t,self_t>();
257 }
258 template <class R>
259 inline detail::operator_<detail::op_pow,self_t,R>
260 pow(self_t const&, R const&)
261 {
262 return detail::operator_<detail::op_pow,self_t,R>();
263 }
264 template <class L>
265 inline detail::operator_<detail::op_pow,L,self_t>
266 pow(L const&, self_t const&)
267 {
268 return detail::operator_<detail::op_pow,L,self_t>();
269 }
270# endif
271}
272
273
274# define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \
275namespace detail \
276{ \
277 template <> \
278 struct operator_l<op_##id> \
279 { \
280 template <class L, class R> \
281 struct apply \
282 { \
283 typedef typename unwrap_wrapper_<L>::type lhs; \
284 typedef typename unwrap_wrapper_<R>::type rhs; \
285 static PyObject* \
286 execute(back_reference<lhs&> l, rhs const& r) \
287 { \
288 l.get() op r; \
289 return python::incref(l.source().ptr()); \
290 } \
291 }; \
292 static char const* name() { return "__" #id "__"; } \
293 }; \
294} \
295namespace self_ns \
296{ \
297 template <class R> \
298 inline detail::operator_<detail::op_##id,self_t,R> \
299 operator op(self_t const&, R const&) \
300 { \
301 return detail::operator_<detail::op_##id,self_t,R>(); \
302 } \
303}
304
305BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=)
306BOOST_PYTHON_INPLACE_OPERATOR(isub,-=)
307BOOST_PYTHON_INPLACE_OPERATOR(imul,*=)
308BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=)
309BOOST_PYTHON_INPLACE_OPERATOR(imod,%=)
310BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=)
311BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=)
312BOOST_PYTHON_INPLACE_OPERATOR(iand,&=)
313BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=)
314BOOST_PYTHON_INPLACE_OPERATOR(ior,|=)
315
316# define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name) \
317namespace detail \
318{ \
319 template <> \
320 struct operator_1<op_##id> \
321 { \
322 template <class T> \
323 struct apply \
324 { \
325 typedef typename unwrap_wrapper_<T>::type self_t; \
326 static PyObject* execute(self_t& x) \
327 { \
328 return detail::convert_result(op(x)); \
329 } \
330 }; \
331 static char const* name() { return "__" #id "__"; } \
332 }; \
333} \
334namespace self_ns \
335{ \
336 inline detail::operator_<detail::op_##id> \
337 func_name(self_t const&) \
338 { \
339 return detail::operator_<detail::op_##id>(); \
340 } \
341}
342# undef BOOST_PYTHON_INPLACE_OPERATOR
343
344BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
345BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
346BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
347BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
348#if PY_VERSION_HEX >= 0x03000000
349BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!)
350#else
351BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
352#endif
353BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
354BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
355BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
356BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
357BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
358BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr)
359# undef BOOST_PYTHON_UNARY_OPERATOR
360
361}} // namespace boost::python
362
363# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
364using boost::python::self_ns::abs;
365using boost::python::self_ns::int_;
366using boost::python::self_ns::long_;
367using boost::python::self_ns::float_;
368using boost::python::self_ns::complex_;
369using boost::python::self_ns::str;
370using boost::python::self_ns::repr;
371using boost::python::self_ns::pow;
372# endif
373
374#endif // OPERATORS_DWA2002530_HPP
375

source code of boost/boost/python/operators.hpp