Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/python/operators.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef OPERATORS_DWA2002530_HPP
0006 # define OPERATORS_DWA2002530_HPP
0007 
0008 # include <boost/python/detail/prefix.hpp>
0009 
0010 # include <boost/python/def_visitor.hpp>
0011 # include <boost/python/converter/arg_to_python.hpp>
0012 # include <boost/python/detail/operator_id.hpp>
0013 # include <boost/python/detail/not_specified.hpp>
0014 # include <boost/python/back_reference.hpp>
0015 # include <boost/mpl/if.hpp>
0016 # include <boost/mpl/eval_if.hpp>
0017 # include <boost/python/self.hpp>
0018 # include <boost/python/other.hpp>
0019 # include <boost/lexical_cast.hpp>
0020 # include <boost/python/refcount.hpp>
0021 # include <boost/python/detail/unwrap_wrapper.hpp>
0022 # include <string>
0023 # include <complex>
0024 
0025 namespace boost { namespace python { 
0026 
0027 namespace detail
0028 {
0029   // This is essentially the old v1 to_python(). It will be eliminated
0030   // once the public interface for to_python is settled on.
0031   template <class T>
0032   PyObject* convert_result(T const& x)
0033   {
0034       return converter::arg_to_python<T>(x).release();
0035   }
0036 
0037   // Operator implementation template declarations. The nested apply
0038   // declaration here keeps MSVC6 happy.
0039   template <operator_id> struct operator_l
0040   {
0041       template <class L, class R> struct apply;
0042   };
0043   
0044   template <operator_id> struct operator_r
0045   {
0046       template <class L, class R> struct apply;
0047   };
0048 
0049   template <operator_id> struct operator_1
0050   {
0051       template <class T> struct apply;
0052   };
0053 
0054   // MSVC6 doesn't want us to do this sort of inheritance on a nested
0055   // class template, so we use this layer of indirection to avoid
0056   // ::template<...> on the nested apply functions below
0057   template <operator_id id, class L, class R>
0058   struct operator_l_inner
0059       : operator_l<id>::template apply<L,R>
0060   {};
0061       
0062   template <operator_id id, class L, class R>
0063   struct operator_r_inner
0064       : operator_r<id>::template apply<L,R>
0065   {};
0066 
0067   template <operator_id id, class T>
0068   struct operator_1_inner
0069       : operator_1<id>::template apply<T>
0070   {};
0071       
0072   // Define three different binary_op templates which take care of
0073   // these cases:
0074   //    self op self
0075   //    self op R
0076   //    L op self
0077   // 
0078   // The inner apply metafunction is used to adjust the operator to
0079   // the class type being defined. Inheritance of the outer class is
0080   // simply used to provide convenient access to the operation's
0081   // name().
0082 
0083   // self op self
0084   template <operator_id id>
0085   struct binary_op : operator_l<id>
0086   {
0087       template <class T>
0088       struct apply : operator_l_inner<id,T,T>
0089       {
0090       };
0091   };
0092 
0093   // self op R
0094   template <operator_id id, class R>
0095   struct binary_op_l : operator_l<id>
0096   {
0097       template <class T>
0098       struct apply : operator_l_inner<id,T,R>
0099       {
0100       };
0101   };
0102 
0103   // L op self
0104   template <operator_id id, class L>
0105   struct binary_op_r : operator_r<id>
0106   {
0107       template <class T>
0108       struct apply : operator_r_inner<id,L,T>
0109       {
0110       };
0111   };
0112 
0113   template <operator_id id>
0114   struct unary_op : operator_1<id>
0115   {
0116       template <class T>
0117       struct apply : operator_1_inner<id,T>
0118       {
0119       };
0120   };
0121 
0122   // This type is what actually gets returned from operators used on
0123   // self_t
0124   template <operator_id id, class L = not_specified, class R = not_specified>
0125   struct operator_
0126     : def_visitor<operator_<id,L,R> >
0127   {
0128    private:
0129       template <class ClassT>
0130       void visit(ClassT& cl) const
0131       {
0132           typedef typename mpl::eval_if<
0133               is_same<L,self_t>
0134             , mpl::if_<
0135                   is_same<R,self_t>
0136                 , binary_op<id>
0137                 , binary_op_l<
0138                       id
0139                     , BOOST_DEDUCED_TYPENAME unwrap_other<R>::type
0140                   >
0141               >
0142             , mpl::if_<
0143                   is_same<L,not_specified>
0144                 , unary_op<id>
0145                 , binary_op_r<
0146                       id
0147                     , BOOST_DEDUCED_TYPENAME unwrap_other<L>::type
0148                   >
0149               >
0150           >::type generator;
0151       
0152           cl.def(
0153               generator::name()
0154             , &generator::template apply<
0155                  BOOST_DEDUCED_TYPENAME ClassT::wrapped_type
0156               >::execute
0157           );
0158       }
0159     
0160       friend class python::def_visitor_access;
0161   };
0162 }
0163 
0164 # define BOOST_PYTHON_BINARY_OPERATION(id, rid, expr)       \
0165 namespace detail                                            \
0166 {                                                           \
0167   template <>                                               \
0168   struct operator_l<op_##id>                                \
0169   {                                                         \
0170       template <class L, class R>                           \
0171       struct apply                                          \
0172       {                                                     \
0173           typedef typename unwrap_wrapper_<L>::type lhs;    \
0174           typedef typename unwrap_wrapper_<R>::type rhs;    \
0175           static PyObject* execute(lhs& l, rhs const& r)    \
0176           {                                                 \
0177               return detail::convert_result(expr);          \
0178           }                                                 \
0179       };                                                    \
0180       static char const* name() { return "__" #id "__"; }   \
0181   };                                                        \
0182                                                             \
0183   template <>                                               \
0184   struct operator_r<op_##id>                                \
0185   {                                                         \
0186       template <class L, class R>                           \
0187       struct apply                                          \
0188       {                                                     \
0189           typedef typename unwrap_wrapper_<L>::type lhs;    \
0190           typedef typename unwrap_wrapper_<R>::type rhs;    \
0191           static PyObject* execute(rhs& r, lhs const& l)    \
0192           {                                                 \
0193               return detail::convert_result(expr);          \
0194           }                                                 \
0195       };                                                    \
0196       static char const* name() { return "__" #rid "__"; }  \
0197   };                                                        \
0198 } 
0199 
0200 # define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op)      \
0201 BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r)          \
0202 namespace self_ns                                       \
0203 {                                                       \
0204   template <class L, class R>                           \
0205   inline detail::operator_<detail::op_##id,L,R>         \
0206   operator op(L const&, R const&)                       \
0207   {                                                     \
0208       return detail::operator_<detail::op_##id,L,R>();  \
0209   }                                                     \
0210 }
0211   
0212 BOOST_PYTHON_BINARY_OPERATOR(add, radd, +)
0213 BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -)
0214 BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *)
0215 #if PY_VERSION_HEX >= 0x03000000
0216     BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /)
0217 #else
0218     BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
0219 #endif
0220 BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
0221 BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
0222 BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
0223 BOOST_PYTHON_BINARY_OPERATOR(and, rand, &)
0224 BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^)
0225 BOOST_PYTHON_BINARY_OPERATOR(or, ror, |)
0226 BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >)
0227 BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=)
0228 BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <)
0229 BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=)
0230 BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==)
0231 BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=)
0232 # undef BOOST_PYTHON_BINARY_OPERATOR
0233     
0234 // pow isn't an operator in C++; handle it specially.
0235 BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r))
0236 # undef BOOST_PYTHON_BINARY_OPERATION
0237     
0238 namespace self_ns
0239 {
0240 # ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
0241   template <class L, class R>
0242   inline detail::operator_<detail::op_pow,L,R>
0243   pow(L const&, R const&)
0244   {
0245       return detail::operator_<detail::op_pow,L,R>();
0246   }
0247 # else
0248   // When there's no argument-dependent lookup, we need these
0249   // overloads to handle the case when everything is imported into the
0250   // global namespace. Note that the plain overload below does /not/
0251   // take const& arguments. This is needed by MSVC6 at least, or it
0252   // complains of ambiguities, since there's no partial ordering.
0253   inline detail::operator_<detail::op_pow,self_t,self_t>
0254   pow(self_t, self_t)
0255   {
0256       return detail::operator_<detail::op_pow,self_t,self_t>();
0257   }
0258   template <class R>
0259   inline detail::operator_<detail::op_pow,self_t,R>
0260   pow(self_t const&, R const&)
0261   {
0262       return detail::operator_<detail::op_pow,self_t,R>();
0263   }
0264   template <class L>
0265   inline detail::operator_<detail::op_pow,L,self_t>
0266   pow(L const&, self_t const&)
0267   {
0268       return detail::operator_<detail::op_pow,L,self_t>();
0269   }
0270 # endif 
0271 }
0272 
0273 
0274 # define BOOST_PYTHON_INPLACE_OPERATOR(id, op)                  \
0275 namespace detail                                                \
0276 {                                                               \
0277   template <>                                                   \
0278   struct operator_l<op_##id>                                    \
0279   {                                                             \
0280       template <class L, class R>                               \
0281       struct apply                                              \
0282       {                                                         \
0283           typedef typename unwrap_wrapper_<L>::type lhs;        \
0284           typedef typename unwrap_wrapper_<R>::type rhs;        \
0285           static PyObject*                                      \
0286           execute(back_reference<lhs&> l, rhs const& r)         \
0287           {                                                     \
0288               l.get() op r;                                     \
0289               return python::incref(l.source().ptr());          \
0290           }                                                     \
0291       };                                                        \
0292       static char const* name() { return "__" #id "__"; }       \
0293   };                                                            \
0294 }                                                               \
0295 namespace self_ns                                               \
0296 {                                                               \
0297   template <class R>                                            \
0298   inline detail::operator_<detail::op_##id,self_t,R>            \
0299   operator op(self_t const&, R const&)                          \
0300   {                                                             \
0301       return detail::operator_<detail::op_##id,self_t,R>();     \
0302   }                                                             \
0303 }
0304 
0305 BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=)
0306 BOOST_PYTHON_INPLACE_OPERATOR(isub,-=)
0307 BOOST_PYTHON_INPLACE_OPERATOR(imul,*=)
0308 BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=)
0309 BOOST_PYTHON_INPLACE_OPERATOR(imod,%=)
0310 BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=)
0311 BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=)
0312 BOOST_PYTHON_INPLACE_OPERATOR(iand,&=)
0313 BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=)
0314 BOOST_PYTHON_INPLACE_OPERATOR(ior,|=)
0315     
0316 # define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name)         \
0317 namespace detail                                                \
0318 {                                                               \
0319   template <>                                                   \
0320   struct operator_1<op_##id>                                    \
0321   {                                                             \
0322       template <class T>                                        \
0323       struct apply                                              \
0324       {                                                         \
0325           typedef typename unwrap_wrapper_<T>::type self_t;     \
0326           static PyObject* execute(self_t& x)                   \
0327           {                                                     \
0328               return detail::convert_result(op(x));             \
0329           }                                                     \
0330       };                                                        \
0331       static char const* name() { return "__" #id "__"; }       \
0332   };                                                            \
0333 }                                                               \
0334 namespace self_ns                                               \
0335 {                                                               \
0336   inline detail::operator_<detail::op_##id>                     \
0337   func_name(self_t const&)                                      \
0338   {                                                             \
0339       return detail::operator_<detail::op_##id>();              \
0340   }                                                             \
0341 }
0342 # undef BOOST_PYTHON_INPLACE_OPERATOR
0343 
0344 BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
0345 BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
0346 BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
0347 BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
0348 #if PY_VERSION_HEX >= 0x03000000
0349 BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!)
0350 #else
0351 BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
0352 #endif
0353 BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
0354 BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
0355 BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
0356 BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
0357 BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
0358 BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr)
0359 # undef BOOST_PYTHON_UNARY_OPERATOR
0360 
0361 }} // namespace boost::python
0362 
0363 # ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
0364 using boost::python::self_ns::abs;
0365 using boost::python::self_ns::int_;
0366 using boost::python::self_ns::long_;
0367 using boost::python::self_ns::float_;
0368 using boost::python::self_ns::complex_;
0369 using boost::python::self_ns::str;
0370 using boost::python::self_ns::repr;
0371 using boost::python::self_ns::pow;
0372 # endif
0373 
0374 #endif // OPERATORS_DWA2002530_HPP