Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/python/operators.hpp @ 35

Last change on this file since 35 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 13.6 KB
Line 
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, *)
215BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
216BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
217BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
218BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
219BOOST_PYTHON_BINARY_OPERATOR(and, rand, &)
220BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^)
221BOOST_PYTHON_BINARY_OPERATOR(or, ror, |)
222BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >)
223BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=)
224BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <)
225BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=)
226BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==)
227BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=)
228# undef BOOST_PYTHON_BINARY_OPERATOR
229   
230// pow isn't an operator in C++; handle it specially.
231BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r))
232# undef BOOST_PYTHON_BINARY_OPERATION
233   
234namespace 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)                  \
271namespace 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}                                                               \
291namespace 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
301BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=)
302BOOST_PYTHON_INPLACE_OPERATOR(isub,-=)
303BOOST_PYTHON_INPLACE_OPERATOR(imul,*=)
304BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=)
305BOOST_PYTHON_INPLACE_OPERATOR(imod,%=)
306BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=)
307BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=)
308BOOST_PYTHON_INPLACE_OPERATOR(iand,&=)
309BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=)
310BOOST_PYTHON_INPLACE_OPERATOR(ior,|=)
311   
312# define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name)         \
313namespace 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}                                                               \
330namespace 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
340BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
341BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
342BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
343BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
344BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
345BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
346BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
347BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
348BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
349BOOST_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
355using boost::python::self_ns::abs;
356using boost::python::self_ns::int_;
357using boost::python::self_ns::long_;
358using boost::python::self_ns::float_;
359using boost::python::self_ns::complex_;
360using boost::python::self_ns::str;
361using boost::python::self_ns::pow;
362# endif
363
364#endif // OPERATORS_DWA2002530_HPP
Note: See TracBrowser for help on using the repository browser.