summaryrefslogtreecommitdiff
path: root/boost/python/operators.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/python/operators.hpp')
-rw-r--r--boost/python/operators.hpp374
1 files changed, 374 insertions, 0 deletions
diff --git a/boost/python/operators.hpp b/boost/python/operators.hpp
new file mode 100644
index 0000000000..ea2be7b98f
--- /dev/null
+++ b/boost/python/operators.hpp
@@ -0,0 +1,374 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef OPERATORS_DWA2002530_HPP
+# define OPERATORS_DWA2002530_HPP
+
+# include <boost/python/detail/prefix.hpp>
+
+# include <boost/python/def_visitor.hpp>
+# include <boost/python/converter/arg_to_python.hpp>
+# include <boost/python/detail/operator_id.hpp>
+# include <boost/python/detail/not_specified.hpp>
+# include <boost/python/back_reference.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/eval_if.hpp>
+# include <boost/python/self.hpp>
+# include <boost/python/other.hpp>
+# include <boost/lexical_cast.hpp>
+# include <boost/python/refcount.hpp>
+# include <boost/python/detail/unwrap_wrapper.hpp>
+# include <string>
+# include <complex>
+
+namespace boost { namespace python {
+
+namespace detail
+{
+ // This is essentially the old v1 to_python(). It will be eliminated
+ // once the public interface for to_python is settled on.
+ template <class T>
+ PyObject* convert_result(T const& x)
+ {
+ return converter::arg_to_python<T>(x).release();
+ }
+
+ // Operator implementation template declarations. The nested apply
+ // declaration here keeps MSVC6 happy.
+ template <operator_id> struct operator_l
+ {
+ template <class L, class R> struct apply;
+ };
+
+ template <operator_id> struct operator_r
+ {
+ template <class L, class R> struct apply;
+ };
+
+ template <operator_id> struct operator_1
+ {
+ template <class T> struct apply;
+ };
+
+ // MSVC6 doesn't want us to do this sort of inheritance on a nested
+ // class template, so we use this layer of indirection to avoid
+ // ::template<...> on the nested apply functions below
+ template <operator_id id, class L, class R>
+ struct operator_l_inner
+ : operator_l<id>::template apply<L,R>
+ {};
+
+ template <operator_id id, class L, class R>
+ struct operator_r_inner
+ : operator_r<id>::template apply<L,R>
+ {};
+
+ template <operator_id id, class T>
+ struct operator_1_inner
+ : operator_1<id>::template apply<T>
+ {};
+
+ // Define three different binary_op templates which take care of
+ // these cases:
+ // self op self
+ // self op R
+ // L op self
+ //
+ // The inner apply metafunction is used to adjust the operator to
+ // the class type being defined. Inheritance of the outer class is
+ // simply used to provide convenient access to the operation's
+ // name().
+
+ // self op self
+ template <operator_id id>
+ struct binary_op : operator_l<id>
+ {
+ template <class T>
+ struct apply : operator_l_inner<id,T,T>
+ {
+ };
+ };
+
+ // self op R
+ template <operator_id id, class R>
+ struct binary_op_l : operator_l<id>
+ {
+ template <class T>
+ struct apply : operator_l_inner<id,T,R>
+ {
+ };
+ };
+
+ // L op self
+ template <operator_id id, class L>
+ struct binary_op_r : operator_r<id>
+ {
+ template <class T>
+ struct apply : operator_r_inner<id,L,T>
+ {
+ };
+ };
+
+ template <operator_id id>
+ struct unary_op : operator_1<id>
+ {
+ template <class T>
+ struct apply : operator_1_inner<id,T>
+ {
+ };
+ };
+
+ // This type is what actually gets returned from operators used on
+ // self_t
+ template <operator_id id, class L = not_specified, class R = not_specified>
+ struct operator_
+ : def_visitor<operator_<id,L,R> >
+ {
+ private:
+ template <class ClassT>
+ void visit(ClassT& cl) const
+ {
+ typedef typename mpl::eval_if<
+ is_same<L,self_t>
+ , mpl::if_<
+ is_same<R,self_t>
+ , binary_op<id>
+ , binary_op_l<
+ id
+ , BOOST_DEDUCED_TYPENAME unwrap_other<R>::type
+ >
+ >
+ , mpl::if_<
+ is_same<L,not_specified>
+ , unary_op<id>
+ , binary_op_r<
+ id
+ , BOOST_DEDUCED_TYPENAME unwrap_other<L>::type
+ >
+ >
+ >::type generator;
+
+ cl.def(
+ generator::name()
+ , &generator::template apply<
+ BOOST_DEDUCED_TYPENAME ClassT::wrapped_type
+ >::execute
+ );
+ }
+
+ friend class python::def_visitor_access;
+ };
+}
+
+# define BOOST_PYTHON_BINARY_OPERATION(id, rid, expr) \
+namespace detail \
+{ \
+ template <> \
+ struct operator_l<op_##id> \
+ { \
+ template <class L, class R> \
+ struct apply \
+ { \
+ typedef typename unwrap_wrapper_<L>::type lhs; \
+ typedef typename unwrap_wrapper_<R>::type rhs; \
+ static PyObject* execute(lhs& l, rhs const& r) \
+ { \
+ return detail::convert_result(expr); \
+ } \
+ }; \
+ static char const* name() { return "__" #id "__"; } \
+ }; \
+ \
+ template <> \
+ struct operator_r<op_##id> \
+ { \
+ template <class L, class R> \
+ struct apply \
+ { \
+ typedef typename unwrap_wrapper_<L>::type lhs; \
+ typedef typename unwrap_wrapper_<R>::type rhs; \
+ static PyObject* execute(rhs& r, lhs const& l) \
+ { \
+ return detail::convert_result(expr); \
+ } \
+ }; \
+ static char const* name() { return "__" #rid "__"; } \
+ }; \
+}
+
+# define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op) \
+BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r) \
+namespace self_ns \
+{ \
+ template <class L, class R> \
+ inline detail::operator_<detail::op_##id,L,R> \
+ operator op(L const&, R const&) \
+ { \
+ return detail::operator_<detail::op_##id,L,R>(); \
+ } \
+}
+
+BOOST_PYTHON_BINARY_OPERATOR(add, radd, +)
+BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -)
+BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *)
+#if PY_VERSION_HEX >= 0x03000000
+ BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /)
+#else
+ BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
+#endif
+BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
+BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
+BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
+BOOST_PYTHON_BINARY_OPERATOR(and, rand, &)
+BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^)
+BOOST_PYTHON_BINARY_OPERATOR(or, ror, |)
+BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >)
+BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=)
+BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <)
+BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=)
+BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==)
+BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=)
+# undef BOOST_PYTHON_BINARY_OPERATOR
+
+// pow isn't an operator in C++; handle it specially.
+BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r))
+# undef BOOST_PYTHON_BINARY_OPERATION
+
+namespace self_ns
+{
+# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
+ template <class L, class R>
+ inline detail::operator_<detail::op_pow,L,R>
+ pow(L const&, R const&)
+ {
+ return detail::operator_<detail::op_pow,L,R>();
+ }
+# else
+ // When there's no argument-dependent lookup, we need these
+ // overloads to handle the case when everything is imported into the
+ // global namespace. Note that the plain overload below does /not/
+ // take const& arguments. This is needed by MSVC6 at least, or it
+ // complains of ambiguities, since there's no partial ordering.
+ inline detail::operator_<detail::op_pow,self_t,self_t>
+ pow(self_t, self_t)
+ {
+ return detail::operator_<detail::op_pow,self_t,self_t>();
+ }
+ template <class R>
+ inline detail::operator_<detail::op_pow,self_t,R>
+ pow(self_t const&, R const&)
+ {
+ return detail::operator_<detail::op_pow,self_t,R>();
+ }
+ template <class L>
+ inline detail::operator_<detail::op_pow,L,self_t>
+ pow(L const&, self_t const&)
+ {
+ return detail::operator_<detail::op_pow,L,self_t>();
+ }
+# endif
+}
+
+
+# define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \
+namespace detail \
+{ \
+ template <> \
+ struct operator_l<op_##id> \
+ { \
+ template <class L, class R> \
+ struct apply \
+ { \
+ typedef typename unwrap_wrapper_<L>::type lhs; \
+ typedef typename unwrap_wrapper_<R>::type rhs; \
+ static PyObject* \
+ execute(back_reference<lhs&> l, rhs const& r) \
+ { \
+ l.get() op r; \
+ return python::incref(l.source().ptr()); \
+ } \
+ }; \
+ static char const* name() { return "__" #id "__"; } \
+ }; \
+} \
+namespace self_ns \
+{ \
+ template <class R> \
+ inline detail::operator_<detail::op_##id,self_t,R> \
+ operator op(self_t const&, R const&) \
+ { \
+ return detail::operator_<detail::op_##id,self_t,R>(); \
+ } \
+}
+
+BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=)
+BOOST_PYTHON_INPLACE_OPERATOR(isub,-=)
+BOOST_PYTHON_INPLACE_OPERATOR(imul,*=)
+BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=)
+BOOST_PYTHON_INPLACE_OPERATOR(imod,%=)
+BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=)
+BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=)
+BOOST_PYTHON_INPLACE_OPERATOR(iand,&=)
+BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=)
+BOOST_PYTHON_INPLACE_OPERATOR(ior,|=)
+
+# define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name) \
+namespace detail \
+{ \
+ template <> \
+ struct operator_1<op_##id> \
+ { \
+ template <class T> \
+ struct apply \
+ { \
+ typedef typename unwrap_wrapper_<T>::type self_t; \
+ static PyObject* execute(self_t& x) \
+ { \
+ return detail::convert_result(op(x)); \
+ } \
+ }; \
+ static char const* name() { return "__" #id "__"; } \
+ }; \
+} \
+namespace self_ns \
+{ \
+ inline detail::operator_<detail::op_##id> \
+ func_name(self_t const&) \
+ { \
+ return detail::operator_<detail::op_##id>(); \
+ } \
+}
+# undef BOOST_PYTHON_INPLACE_OPERATOR
+
+BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
+BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
+BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
+BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
+#if PY_VERSION_HEX >= 0x03000000
+BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!)
+#else
+BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
+#endif
+BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
+BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
+BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
+BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
+BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
+BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr)
+# undef BOOST_PYTHON_UNARY_OPERATOR
+
+}} // namespace boost::python
+
+# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
+using boost::python::self_ns::abs;
+using boost::python::self_ns::int_;
+using boost::python::self_ns::long_;
+using boost::python::self_ns::float_;
+using boost::python::self_ns::complex_;
+using boost::python::self_ns::str;
+using boost::python::self_ns::repr;
+using boost::python::self_ns::pow;
+# endif
+
+#endif // OPERATORS_DWA2002530_HPP