Define both __div__ and __truediv__ for Python 2

Python 2 requires both `__div__` and `__truediv__` (and variants) for
compatibility with both regular Python 2 and Python 2 under `from
__future__ import division`.  Without both, division fails in one or the
other case.
This commit is contained in:
Jason Rhinelander 2017-05-20 20:34:51 -04:00
parent 1ac51a02f7
commit 35998a0314

View File

@ -13,6 +13,9 @@
#if defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type()))
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#endif
NAMESPACE_BEGIN(pybind11)
@ -54,6 +57,11 @@ template <op_id id, op_type ot, typename L, typename R> struct op_ {
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
using op = op_impl<id, ot, Base, L_type, R_type>;
cl.def(op::name(), &op::execute, is_operator(), extra...);
#if PY_MAJOR_VERSION < 3
if (id == op_truediv || id == op_itruediv)
cl.def(id == op_itruediv ? "__idiv__" : ot == op_l ? "__div__" : "__rdiv__",
&op::execute, is_operator(), extra...);
#endif
}
template <typename Class, typename... Extra> void execute_cast(Class &cl, const Extra&... extra) const {
using Base = typename Class::type;
@ -61,6 +69,11 @@ template <op_id id, op_type ot, typename L, typename R> struct op_ {
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
using op = op_impl<id, ot, Base, L_type, R_type>;
cl.def(op::name(), &op::execute_cast, is_operator(), extra...);
#if PY_MAJOR_VERSION < 3
if (id == op_truediv || id == op_itruediv)
cl.def(id == op_itruediv ? "__idiv__" : ot == op_l ? "__div__" : "__rdiv__",
&op::execute, is_operator(), extra...);
#endif
}
};
@ -108,11 +121,7 @@ inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) {
PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r)
PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r)
PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l * r)
#if PY_MAJOR_VERSION >= 3
PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r)
#else
PYBIND11_BINARY_OPERATOR(div, rdiv, operator/, l / r)
#endif
PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r)
PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r)
PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r)
@ -129,11 +138,7 @@ PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r)
PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r)
PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r)
PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r)
#if PY_MAJOR_VERSION >= 3
PYBIND11_INPLACE_OPERATOR(itruediv, operator/=, l /= r)
#else
PYBIND11_INPLACE_OPERATOR(idiv, operator/=, l /= r)
#endif
PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r)
PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r)
PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r)
@ -156,3 +161,7 @@ NAMESPACE_END(detail)
using detail::self;
NAMESPACE_END(pybind11)
#if defined(_MSC_VER)
# pragma warning(pop)
#endif