ossrv_pub/boost_apis/boost/python/operators.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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