source: NonGTP/Boost/boost/python/operators.hpp @ 857

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