os/ossrv/ossrv_pub/boost_apis/boost/python/operators.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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