mirror of
https://github.com/boostorg/python.git
synced 2026-01-25 06:22:15 +00:00
operator support
[SVN r14068]
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/data_members.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -37,6 +38,9 @@ namespace detail
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable;
|
||||
|
||||
template <detail::operator_id, class L, class R>
|
||||
struct operator_;
|
||||
|
||||
// Register a to_python converter for a class T, depending on the
|
||||
// type of the first (tag) argument. The 2nd argument is a pointer
|
||||
// to the type of holder that must be created. The 3rd argument is a
|
||||
@@ -117,6 +121,18 @@ class class_ : public objects::class_base
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <detail::operator_id id, class L, class R>
|
||||
self& def(detail::operator_<id,L,R> const& op)
|
||||
{
|
||||
typedef detail::operator_<id,L,R> op_t;
|
||||
// Use function::add_to_namespace to achieve overloading if
|
||||
// appropriate.
|
||||
objects::function::add_to_namespace(
|
||||
this->object(), op.name(),
|
||||
ref(detail::wrap_function(&op_t::template apply<T>::execute)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Define the constructor with the given Args, which should be an
|
||||
// MPL sequence of types.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/converter/callback_to_python_base.hpp>
|
||||
# include <string>
|
||||
# include <complex>
|
||||
|
||||
@@ -33,40 +34,37 @@ namespace converter
|
||||
BOOST_PYTHON_DECL PyObject* do_callback_to_python(PyObject*);
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
template <> struct to_python_value<T&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
}; \
|
||||
template <> struct to_python_value<T const&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
# define BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
template <> struct to_python_value<T&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
}; \
|
||||
template <> struct to_python_value<T const&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
};
|
||||
|
||||
# define BOOST_PYTHON_CALLBACK_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
namespace converter \
|
||||
{ \
|
||||
template <> struct callback_to_python< T > \
|
||||
{ \
|
||||
callback_to_python(T const& x) \
|
||||
: m_held(expr) {} \
|
||||
PyObject* get() const \
|
||||
{ return m_held.get(); } \
|
||||
private: \
|
||||
ref m_held; \
|
||||
}; \
|
||||
# define BOOST_PYTHON_CALLBACK_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
namespace converter \
|
||||
{ \
|
||||
template <> struct callback_to_python< T > \
|
||||
: detail::callback_to_python_holder \
|
||||
{ \
|
||||
callback_to_python(T const& x) \
|
||||
: detail::callback_to_python_holder(expr) {} \
|
||||
}; \
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(T,expr) \
|
||||
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(T,expr) \
|
||||
BOOST_PYTHON_CALLBACK_TO_PYTHON_BY_VALUE(T,expr)
|
||||
|
||||
# define BOOST_PYTHON_TO_INT(T) \
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace detail
|
||||
struct callback_to_python_holder
|
||||
{
|
||||
callback_to_python_holder(PyObject* obj);
|
||||
inline PyObject* get() const;
|
||||
PyObject* get() const;
|
||||
PyObject* get_incref() const;
|
||||
private:
|
||||
ref m_held;
|
||||
};
|
||||
@@ -38,6 +39,13 @@ namespace detail
|
||||
{
|
||||
return m_held.get();
|
||||
}
|
||||
|
||||
inline PyObject* callback_to_python_holder::get_incref() const
|
||||
{
|
||||
PyObject* result = m_held.get();
|
||||
Py_XINCREF(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -57,8 +57,8 @@ template <bool> struct bool_t{};
|
||||
template <class T>
|
||||
inline typeinfo typeid_nonref(boost::type<T>* = 0)
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
|
||||
BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
|
||||
bool const c = is_const<T>::value;
|
||||
bool const v = is_volatile<T>::value;
|
||||
return value_id_accessor<(2 * v + c)>::get((T*)0);
|
||||
}
|
||||
|
||||
|
||||
54
include/boost/python/detail/operator_id.hpp
Executable file
54
include/boost/python/detail/operator_id.hpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef OPERATOR_ID_DWA2002531_HPP
|
||||
# define OPERATOR_ID_DWA2002531_HPP
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
enum operator_id
|
||||
{
|
||||
op_add,
|
||||
op_sub,
|
||||
op_mul,
|
||||
op_div,
|
||||
op_mod,
|
||||
op_divmod,
|
||||
op_pow,
|
||||
op_lshift,
|
||||
op_rshift,
|
||||
op_and,
|
||||
op_xor,
|
||||
op_or,
|
||||
op_neg,
|
||||
op_pos,
|
||||
op_abs,
|
||||
op_invert,
|
||||
op_int,
|
||||
op_long,
|
||||
op_float,
|
||||
op_str,
|
||||
op_cmp,
|
||||
op_gt,
|
||||
op_ge,
|
||||
op_lt,
|
||||
op_le,
|
||||
op_eq,
|
||||
op_ne,
|
||||
op_iadd,
|
||||
op_isub,
|
||||
op_imul,
|
||||
op_idiv,
|
||||
op_imod,
|
||||
op_ilshift,
|
||||
op_irshift,
|
||||
op_iand,
|
||||
op_ixor,
|
||||
op_ior
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // OPERATOR_ID_DWA2002531_HPP
|
||||
284
include/boost/python/operators2.hpp
Executable file
284
include/boost/python/operators2.hpp
Executable file
@@ -0,0 +1,284 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef OPERATORS2_DWA2002530_HPP
|
||||
# define OPERATORS2_DWA2002530_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/callback.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
# include <boost/mpl/select_type.hpp>
|
||||
# include <boost/python/self.hpp>
|
||||
# include <boost/python/other.hpp>
|
||||
|
||||
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::callback_to_python<T>(x).get_incref();
|
||||
}
|
||||
|
||||
// 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_
|
||||
: mpl::select_type<
|
||||
(is_same<L,self_t>::value)
|
||||
, typename mpl::select_type<
|
||||
(is_same<R,self_t>::value)
|
||||
, binary_op<id>
|
||||
, binary_op_l<id,typename unwrap_other<R>::type>
|
||||
>::type
|
||||
, typename mpl::select_type<
|
||||
(is_same<L,not_specified>::value)
|
||||
, unary_op<id>
|
||||
, binary_op_r<id,typename unwrap_other<L>::type>
|
||||
>::type
|
||||
>::type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op) \
|
||||
namespace detail \
|
||||
{ \
|
||||
template <> \
|
||||
struct operator_l<op_##id> \
|
||||
{ \
|
||||
template <class L, class R> \
|
||||
struct apply \
|
||||
{ \
|
||||
static inline PyObject* execute(L const& l, R const& r) \
|
||||
{ \
|
||||
return detail::convert_result(l op r); \
|
||||
} \
|
||||
}; \
|
||||
static char const* name() { return "__" #id "__"; } \
|
||||
}; \
|
||||
\
|
||||
template <> \
|
||||
struct operator_r<op_##id> \
|
||||
{ \
|
||||
template <class L, class R> \
|
||||
struct apply \
|
||||
{ \
|
||||
static inline PyObject* execute(R const& r, L const& l) \
|
||||
{ \
|
||||
return detail::convert_result(l op r); \
|
||||
} \
|
||||
}; \
|
||||
static char const* name() { return "__" #rid "__"; } \
|
||||
}; \
|
||||
} \
|
||||
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, *)
|
||||
BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
|
||||
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, !=)
|
||||
|
||||
# define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \
|
||||
namespace detail \
|
||||
{ \
|
||||
template <> \
|
||||
struct operator_l<op_##id> \
|
||||
{ \
|
||||
template <class L, class R> \
|
||||
struct apply \
|
||||
{ \
|
||||
static inline PyObject* \
|
||||
execute(back_reference<L&> l, R const& r) \
|
||||
{ \
|
||||
l.get() op r; \
|
||||
return l.reference().release(); \
|
||||
} \
|
||||
}; \
|
||||
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 \
|
||||
{ \
|
||||
static PyObject* execute(T const& 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>(); \
|
||||
} \
|
||||
}
|
||||
|
||||
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~)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
|
||||
|
||||
}} // 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_;
|
||||
# endif
|
||||
|
||||
#endif // OPERATORS2_DWA2002530_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
113
include/boost/python/other.hpp
Executable file
113
include/boost/python/other.hpp
Executable file
@@ -0,0 +1,113 @@
|
||||
#ifndef OTHER_DWA20020601_HPP
|
||||
# define OTHER_DWA20020601_HPP
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
# if _MSC_VER+0 >= 1020
|
||||
# pragma once
|
||||
# endif
|
||||
|
||||
# include <boost/config.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template<class T> struct other
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
class is_other
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_other<other<T> >
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_other
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_other<other<T> >
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
}
|
||||
# else // no partial specialization
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_other_t)[1];
|
||||
typedef char (&no_other_t)[2];
|
||||
|
||||
no_other_t is_other_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_other_t is_other_test(type< other<T> >);
|
||||
|
||||
template<bool wrapped>
|
||||
struct other_unwrapper
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct other_unwrapper<true>
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename T::type type;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_other
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_other_test(type<T>()))
|
||||
== sizeof(detail::yes_other_t)));
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class unwrap_other
|
||||
: public detail::other_unwrapper<
|
||||
is_other<T>::value
|
||||
>::template apply<T>
|
||||
{};
|
||||
}
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // #ifndef OTHER_DWA20020601_HPP
|
||||
36
include/boost/python/self.hpp
Executable file
36
include/boost/python/self.hpp
Executable file
@@ -0,0 +1,36 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef SELF_DWA2002531_HPP
|
||||
# define SELF_DWA2002531_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
//# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
# define BOOST_PYTHON_SELF_IS_CLASS
|
||||
//# endif
|
||||
|
||||
// Sink self_t into its own namespace so that we have a safe place to
|
||||
// put the completely general operator templates which operate on
|
||||
// it. It is possible to avoid this, but it turns out to be much more
|
||||
// complicated and finally GCC 2.95.2 chokes on it.
|
||||
namespace self_ns
|
||||
{
|
||||
# ifndef BOOST_PYTHON_SELF_IS_CLASS
|
||||
enum self_t { self };
|
||||
# else
|
||||
struct self_t {};
|
||||
extern BOOST_PYTHON_DECL self_t self;
|
||||
# endif
|
||||
}
|
||||
|
||||
using self_ns::self_t;
|
||||
using self_ns::self;
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // SELF_DWA2002531_HPP
|
||||
@@ -8,12 +8,20 @@
|
||||
#include <boost/python/objects.hpp>
|
||||
#include <boost/python/detail/map_entry.hpp>
|
||||
#include <boost/detail/binary_search.hpp>
|
||||
#include <boost/python/self.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
# ifdef BOOST_PYTHON_SELF_IS_CLASS
|
||||
namespace self_ns
|
||||
{
|
||||
self_t self;
|
||||
}
|
||||
# endif
|
||||
|
||||
instance_holder::instance_holder()
|
||||
: m_next(0)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include <numeric>
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <boost/python/objects.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cstring>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -77,6 +81,67 @@ void function::add_overload(function* overload_)
|
||||
parent->m_overloads = overload_;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
char const* const binary_operator_names[] =
|
||||
{
|
||||
"add__",
|
||||
"and__",
|
||||
"div__",
|
||||
"eq__",
|
||||
"ge__",
|
||||
"gt__",
|
||||
"le__",
|
||||
"lshift__",
|
||||
"lt__",
|
||||
"mod__",
|
||||
"mul__",
|
||||
"ne__",
|
||||
"or__",
|
||||
"radd__",
|
||||
"rand__",
|
||||
"rdiv__",
|
||||
"rlshift__",
|
||||
"rmod__",
|
||||
"rmul__",
|
||||
"ror__",
|
||||
"rrshift__",
|
||||
"rshift__",
|
||||
"rsub__",
|
||||
"rxor__",
|
||||
"sub__",
|
||||
"xor__",
|
||||
};
|
||||
|
||||
inline bool is_binary_operator(char const* name)
|
||||
{
|
||||
return name[0] == '_'
|
||||
&& name[1] == '_'
|
||||
&& std::binary_search(
|
||||
&binary_operator_names[0]
|
||||
, binary_operator_names + sizeof(binary_operator_names)/sizeof(*binary_operator_names)
|
||||
, name + 2
|
||||
, bind<bool>(std::less<int>(),
|
||||
bind(BOOST_CSTD_::strcmp, _1, _2), 0)
|
||||
);
|
||||
}
|
||||
|
||||
// Something for the end of the chain of binary operators
|
||||
PyObject* not_implemented_impl(PyObject*, PyObject*)
|
||||
{
|
||||
Py_INCREF(Py_NotImplemented);
|
||||
return Py_NotImplemented;
|
||||
}
|
||||
|
||||
function* not_implemented_function()
|
||||
{
|
||||
static function* result = new function(py_function(¬_implemented_impl), 2, 3);
|
||||
static ref keeper(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void function::add_to_namespace(
|
||||
ref const& name_space, char const* name_, ref const& attribute)
|
||||
{
|
||||
@@ -99,11 +164,19 @@ void function::add_to_namespace(
|
||||
|
||||
ref existing(PyObject_GetItem(dict, name.get()), ref::null_ok);
|
||||
|
||||
if (existing.get() && existing->ob_type == &function_type)
|
||||
if (existing.get())
|
||||
{
|
||||
static_cast<function*>(existing.get())->add_overload(
|
||||
static_cast<function*>(attribute.get()));
|
||||
return;
|
||||
if (existing->ob_type == &function_type)
|
||||
{
|
||||
static_cast<function*>(attribute.get())->add_overload(
|
||||
static_cast<function*>(existing.get()));
|
||||
}
|
||||
}
|
||||
// Binary operators need an additional overload which returns NotImplemented
|
||||
else if (is_binary_operator(name_))
|
||||
{
|
||||
static_cast<function*>(attribute.get())->add_overload(
|
||||
not_implemented_function());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ bpl-test pearu1 : test_cltree.py cltree.cpp ;
|
||||
bpl-test try : newtest.py m1.cpp m2.cpp ;
|
||||
bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters.cpp ;
|
||||
bpl-test test_pointer_adoption ;
|
||||
bpl-test operators ;
|
||||
bpl-test callbacks ;
|
||||
bpl-test virtual_functions ;
|
||||
bpl-test back_reference ;
|
||||
|
||||
56
test/operators.cpp
Executable file
56
test/operators.cpp
Executable file
@@ -0,0 +1,56 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <string>
|
||||
#include <boost/python/operators2.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include "test_class.hpp"
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
typedef test_class<> X;
|
||||
|
||||
X operator-(X const& l, X const& r) { return X(l.value() - r.value()); }
|
||||
X operator-(int l, X const& r) { return X(l - r.value()); }
|
||||
X operator-(X const& l, int r) { return X(l.value() - r); }
|
||||
|
||||
X operator-(X const& x) { return X(-x.value()); }
|
||||
|
||||
X& operator-=(X& l, X const& r) { l.set(l.value() - r.value()); return l; }
|
||||
|
||||
bool operator<(X const& x, X const& y) { return x.value() < y.value(); }
|
||||
bool operator<(X const& x, int y) { return x.value() < y; }
|
||||
bool operator<(int x, X const& y) { return x < y.value(); }
|
||||
|
||||
X abs(X x) { return X(x.value() < 0 ? -x.value() : x.value()); }
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(operators_ext)
|
||||
{
|
||||
module("operators_ext")
|
||||
.add(
|
||||
class_<X>("X")
|
||||
.def_init(args<int>())
|
||||
.def("value", &X::value)
|
||||
.def(self - self)
|
||||
.def(self - int())
|
||||
.def(other<int>() - self)
|
||||
.def(-self)
|
||||
.def(self < other<int>())
|
||||
.def(self < self)
|
||||
.def(1 < self)
|
||||
.def(self -= self)
|
||||
.def(abs(self))
|
||||
)
|
||||
.add(
|
||||
class_<test_class<1> >("Z")
|
||||
.def_init(args<int>())
|
||||
.def(int_(self))
|
||||
.def(float_(self))
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
75
test/operators.py
Normal file
75
test/operators.py
Normal file
@@ -0,0 +1,75 @@
|
||||
'''
|
||||
>>> from operators_ext import *
|
||||
>>> x = X(42)
|
||||
>>> x.value()
|
||||
42
|
||||
>>> y = x - X(5)
|
||||
>>> y.value()
|
||||
37
|
||||
>>> y = x - 4
|
||||
>>> y.value()
|
||||
38
|
||||
>>> y = 3 - x
|
||||
>>> y.value()
|
||||
-39
|
||||
>>> (-y).value()
|
||||
39
|
||||
|
||||
>>> abs(y).value()
|
||||
39
|
||||
|
||||
>>> x < 10
|
||||
0
|
||||
>>> x < 43
|
||||
1
|
||||
|
||||
>>> 10 < x
|
||||
1
|
||||
>>> 43 < x
|
||||
0
|
||||
|
||||
>>> x < y
|
||||
0
|
||||
>>> y < x
|
||||
1
|
||||
|
||||
------
|
||||
>>> x > 10
|
||||
1
|
||||
>>> x > 43
|
||||
0
|
||||
|
||||
>>> 10 > x
|
||||
0
|
||||
>>> 43 > x
|
||||
1
|
||||
|
||||
>>> x > y
|
||||
1
|
||||
>>> y > x
|
||||
0
|
||||
|
||||
>>> y = x - 5
|
||||
>>> x -= y
|
||||
>>> x.value()
|
||||
5
|
||||
|
||||
>>> z = Z(10)
|
||||
>>> int(z)
|
||||
10
|
||||
>>> float(z)
|
||||
10.0
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
Reference in New Issue
Block a user