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> convert_result(T const & x)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> visitboost::python::detail::operator_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 #if PY_VERSION_HEX >= 0x03000000 216 BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /) 217 #else 218 BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /) 219 #endif 220 BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %) 221 BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<) 222 BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>) 223 BOOST_PYTHON_BINARY_OPERATOR(and, rand, &) 224 BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^) 225 BOOST_PYTHON_BINARY_OPERATOR(or, ror, |) 226 BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >) 227 BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=) 228 BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <) 229 BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=) 230 BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==) 231 BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=) 232 # undef BOOST_PYTHON_BINARY_OPERATOR 233 234 // pow isn't an operator in C++; handle it specially. 235 BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r)) 236 # undef BOOST_PYTHON_BINARY_OPERATION 237 238 namespace self_ns 239 { 240 # ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 241 template <class L, class R> 242 inline detail::operator_<detail::op_pow,L,R> pow(L const &,R const &)243 pow(L const&, R const&) 244 { 245 return detail::operator_<detail::op_pow,L,R>(); 246 } 247 # else 248 // When there's no argument-dependent lookup, we need these 249 // overloads to handle the case when everything is imported into the 250 // global namespace. Note that the plain overload below does /not/ 251 // take const& arguments. This is needed by MSVC6 at least, or it 252 // complains of ambiguities, since there's no partial ordering. 253 inline detail::operator_<detail::op_pow,self_t,self_t> 254 pow(self_t, self_t) 255 { 256 return detail::operator_<detail::op_pow,self_t,self_t>(); 257 } 258 template <class R> 259 inline detail::operator_<detail::op_pow,self_t,R> 260 pow(self_t const&, R const&) 261 { 262 return detail::operator_<detail::op_pow,self_t,R>(); 263 } 264 template <class L> 265 inline detail::operator_<detail::op_pow,L,self_t> 266 pow(L const&, self_t const&) 267 { 268 return detail::operator_<detail::op_pow,L,self_t>(); 269 } 270 # endif 271 } 272 273 274 # define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \ 275 namespace detail \ 276 { \ 277 template <> \ 278 struct operator_l<op_##id> \ 279 { \ 280 template <class L, class R> \ 281 struct apply \ 282 { \ 283 typedef typename unwrap_wrapper_<L>::type lhs; \ 284 typedef typename unwrap_wrapper_<R>::type rhs; \ 285 static PyObject* \ 286 execute(back_reference<lhs&> l, rhs const& r) \ 287 { \ 288 l.get() op r; \ 289 return python::incref(l.source().ptr()); \ 290 } \ 291 }; \ 292 static char const* name() { return "__" #id "__"; } \ 293 }; \ 294 } \ 295 namespace self_ns \ 296 { \ 297 template <class R> \ 298 inline detail::operator_<detail::op_##id,self_t,R> \ 299 operator op(self_t const&, R const&) \ 300 { \ 301 return detail::operator_<detail::op_##id,self_t,R>(); \ 302 } \ 303 } 304 305 BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=) 306 BOOST_PYTHON_INPLACE_OPERATOR(isub,-=) 307 BOOST_PYTHON_INPLACE_OPERATOR(imul,*=) 308 BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=) 309 BOOST_PYTHON_INPLACE_OPERATOR(imod,%=) 310 BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=) 311 BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=) 312 BOOST_PYTHON_INPLACE_OPERATOR(iand,&=) 313 BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=) 314 BOOST_PYTHON_INPLACE_OPERATOR(ior,|=) 315 316 # define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name) \ 317 namespace detail \ 318 { \ 319 template <> \ 320 struct operator_1<op_##id> \ 321 { \ 322 template <class T> \ 323 struct apply \ 324 { \ 325 typedef typename unwrap_wrapper_<T>::type self_t; \ 326 static PyObject* execute(self_t& x) \ 327 { \ 328 return detail::convert_result(op(x)); \ 329 } \ 330 }; \ 331 static char const* name() { return "__" #id "__"; } \ 332 }; \ 333 } \ 334 namespace self_ns \ 335 { \ 336 inline detail::operator_<detail::op_##id> \ 337 func_name(self_t const&) \ 338 { \ 339 return detail::operator_<detail::op_##id>(); \ 340 } \ 341 } 342 # undef BOOST_PYTHON_INPLACE_OPERATOR 343 344 BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-) 345 BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+) 346 BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs) 347 BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~) 348 #if PY_VERSION_HEX >= 0x03000000 349 BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!) 350 #else 351 BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!) 352 #endif 353 BOOST_PYTHON_UNARY_OPERATOR(int, long, int_) 354 BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_) 355 BOOST_PYTHON_UNARY_OPERATOR(float, double, float_) 356 BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_) 357 BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str) 358 BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr) 359 # undef BOOST_PYTHON_UNARY_OPERATOR 360 361 }} // namespace boost::python 362 363 # ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 364 using boost::python::self_ns::abs; 365 using boost::python::self_ns::int_; 366 using boost::python::self_ns::long_; 367 using boost::python::self_ns::float_; 368 using boost::python::self_ns::complex_; 369 using boost::python::self_ns::str; 370 using boost::python::self_ns::repr; 371 using boost::python::self_ns::pow; 372 # endif 373 374 #endif // OPERATORS_DWA2002530_HPP 375