2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-26 06:42:27 +00:00

object operator support

[SVN r14168]
This commit is contained in:
Dave Abrahams
2002-06-18 13:49:09 +00:00
parent 87bda9e124
commit 66f2cd81a8
15 changed files with 771 additions and 432 deletions

View File

@@ -12,11 +12,11 @@
# include <boost/mpl/select_type.hpp>
# include <boost/python/detail/indirect_traits.hpp>
namespace boost { namespace python {
namespace boost { namespace python { namespace api {
class object;
}}
}}}
namespace boost { namespace python { namespace converter {
@@ -142,7 +142,7 @@ inline T* get_managed_object(python::detail::borrowed<T> const volatile* p)
// forward declaration needed because name lookup is bound by the
// definition context.
PyObject* get_managed_object(python::object const&);
PyObject* get_managed_object(python::api::object const&);
}}} // namespace boost::python::converter

View File

@@ -9,6 +9,7 @@
# include <boost/python/object_core.hpp>
# include <boost/python/object_attributes.hpp>
# include <boost/python/object_items.hpp>
# include <boost/python/object_operators.hpp>
namespace boost { namespace python {

View File

@@ -10,51 +10,48 @@
# include <boost/python/object_core.hpp>
# include <boost/python/object_protocol.hpp>
namespace boost { namespace python {
namespace boost { namespace python { namespace api {
namespace detail
struct const_attribute_policies
{
struct const_attribute_policies
{
static object get(object const& target, object const& key);
};
static object get(object const& target, object const& key);
};
struct attribute_policies : const_attribute_policies
{
static object const& set(object const& target, object const& key, object const& value);
};
}
struct attribute_policies : const_attribute_policies
{
static object const& set(object const& target, object const& key, object const& value);
};
//
// implementation
//
inline object_attribute object::_(char const* name)
inline object_attribute object::attr(char const* name)
{
return object_attribute(*this, object(name));
}
inline const_object_attribute object::_(char const* name) const
inline const_object_attribute object::attr(char const* name) const
{
return const_object_attribute(*this, object(name));
}
namespace detail
{
inline object const_attribute_policies::get(object const& target, object const& key)
{
return python::getattr(target, key);
}
inline object const& attribute_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setattr(target, key, value);
return value;
}
inline object const_attribute_policies::get(object const& target, object const& key)
{
return python::getattr(target, key);
}
inline object const& attribute_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setattr(target, key, value);
return value;
}
} // namespace api
namespace converter
{
// These specializations are a lie; the proxies do not directly
@@ -64,13 +61,13 @@ namespace converter
// actually managing the object during the duration of the
// conversion.
template <>
struct is_object_manager<object_attribute>
struct is_object_manager<api::object_attribute>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <>
struct is_object_manager<const_object_attribute>
struct is_object_manager<api::const_object_attribute>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};

View File

@@ -12,122 +12,147 @@
namespace boost { namespace python {
// Put this in an inner namespace so that the generalized operators won't take over
namespace api
{
// This file contains the definition of the object class and enough to
// construct/copy it, but not enough to do operations like
// attribute/item access or addition.
template <class Policies> class proxy;
namespace detail
{
template <class Policies> class proxy;
struct const_attribute_policies;
struct attribute_policies;
struct const_item_policies;
struct item_policies;
}
typedef proxy<detail::const_attribute_policies> const_object_attribute;
typedef proxy<detail::attribute_policies> object_attribute;
typedef proxy<detail::const_item_policies> const_object_item;
typedef proxy<detail::item_policies> object_item;
class object
{
typedef proxy<const_attribute_policies> const_object_attribute;
typedef proxy<attribute_policies> object_attribute;
typedef proxy<const_item_policies> const_object_item;
typedef proxy<item_policies> object_item;
// A way to turn a conrete type T into a type dependent on U. This
// keeps conforming compilers from complaining about returning an
// incomplete T from a template member function (which must be
// defined in the class body to keep MSVC happy).
template <class T, class U>
struct dependent
{
typedef T type;
};
class object
{
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
typedef object const& self_cref;
typedef object const& self_cref;
# else
typedef object self_cref;
typedef object self_cref;
# endif
public:
public:
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// copy constructor without NULL checking, for efficiency
object(object const&);
// copy constructor without NULL checking, for efficiency
object(object const&);
# endif
// explicit conversion from any C++ object to Python
template <class T>
explicit object(T const& x)
: m_ptr(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<T>(x).get())
)
)
{
}
// explicit conversion from any C++ object to Python
template <class T>
explicit object(T const& x)
: m_ptr(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<T>(x).get())
)
)
{
}
// capture this case explicitly to handle string
// literals. Otherwise, they get deduced as char[N]const& above
// and conversion fails at runtime.
explicit object(char const* x)
: m_ptr(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<char const*>(x).get())
)
)
{
// capture this case explicitly to handle string
// literals. Otherwise, they get deduced as char[N]const& above
// and conversion fails at runtime.
explicit object(char const* x)
: m_ptr(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<char const*>(x).get())
)
)
{
}
}
// Throw error_already_set() if the handle is null.
explicit object(handle<> const&);
// Throw error_already_set() if the handle is null.
explicit object(handle<> const&);
// Attribute access via x._("attribute_name")
const_object_attribute _(char const*) const;
object_attribute _(char const*);
// Attribute access via x.attr("attribute_name")
const_object_attribute attr(char const*) const;
object_attribute attr(char const*);
object operator()() const
{
return object(call<handle<> >(m_ptr.get()));
}
object operator()() const
{
return object(call<handle<> >(m_ptr.get()));
}
# ifndef BOOST_PYTHON_GENERATE_CODE
# include <boost/python/preprocessed/object_call.hpp>
# endif
# define BOOST_PYTHON_OBJECT_CALL(nargs,ignored) \
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
object operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
{ \
return object(call<handle<> >(&**this, BOOST_PP_ENUM_PARAMS(nargs, a))); \
}
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
object operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
{ \
return object(call<handle<> >(&**this, BOOST_PP_ENUM_PARAMS(nargs, a))); \
}
BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_OBJECT_CALL, ignored)
BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_OBJECT_CALL, ignored)
// truth value testing
typedef handle<> (object::*bool_type);
operator bool_type() const;
bool operator!() const; // needed for vc6
// truth value testing
typedef handle<> (object::*bool_type);
operator bool_type() const;
bool operator!() const; // needed for vc6
// item access
const_object_item operator[](self_cref) const;
object_item operator[](self_cref);
// item access
const_object_item operator[](self_cref) const;
object_item operator[](self_cref);
template <class T>
const_object_item operator[](T const& key) const
{
return (*this)[object(key)];
}
template <class T>
# if BOOST_MSVC != 1300
typename dependent<const_object_item,T>::type
# else
const_object_item
# endif
operator[](T const& key) const
{
return (*this)[object(key)];
}
template <class T>
object_item operator[](T const& key)
{
return (*this)[object(key)];
}
template <class T>
# if BOOST_MSVC != 1300
typename dependent<object_item,T>::type
# else
object_item
# endif
operator[](T const& key)
{
return (*this)[object(key)];
}
// Underlying object access
PyObject* operator->() const;
PyObject& operator*() const;
// Underlying object access
PyObject* operator->() const;
PyObject& operator*() const;
public: // implementation detail -- for internal use only
object(null_ok<detail::borrowed<PyObject> >*);
object(detail::borrowed<null_ok<PyObject> >*);
object(detail::borrowed<PyObject>*);
class new_pyobject_reference;
object(new_pyobject_reference*);
public: // implementation detail -- for internal use only
object(null_ok<detail::borrowed<PyObject> >*);
object(detail::borrowed<null_ok<PyObject> >*);
object(detail::borrowed<PyObject>*);
class new_pyobject_reference;
object(new_pyobject_reference*);
private:
handle<> m_ptr;
};
private:
handle<> m_ptr;
};
}
using api::object;
//
// Converter Specializations

View File

@@ -10,20 +10,17 @@
# include <boost/python/object_core.hpp>
# include <boost/python/object_protocol.hpp>
namespace boost { namespace python {
namespace boost { namespace python { namespace api {
namespace detail
struct const_item_policies
{
struct const_item_policies
{
static object get(object const& target, object const& key);
};
static object get(object const& target, object const& key);
};
struct item_policies : const_item_policies
{
static object const& set(object const& target, object const& key, object const& value);
};
}
struct item_policies : const_item_policies
{
static object const& set(object const& target, object const& key, object const& value);
};
//
// implementation
@@ -38,23 +35,23 @@ inline const_object_item object::operator[](object::self_cref key) const
return const_object_item(*this, key);
}
namespace detail
{
inline object const_item_policies::get(object const& target, object const& key)
{
return python::getitem(target, key);
}
inline object const& item_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setitem(target, key, value);
return value;
}
inline object const_item_policies::get(object const& target, object const& key)
{
return python::getitem(target, key);
}
inline object const& item_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setitem(target, key, value);
return value;
}
} // namespace api
namespace converter
{
// These specializations are a lie; the proxies do not directly
@@ -64,13 +61,13 @@ namespace converter
// actually managing the object during the duration of the
// conversion.
template <>
struct is_object_manager<object_item>
struct is_object_manager<api::object_item>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <>
struct is_object_manager<const_object_item>
struct is_object_manager<api::const_object_item>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};

View File

@@ -0,0 +1,68 @@
// 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 OBJECT_OPERATORS_DWA2002617_HPP
# define OBJECT_OPERATORS_DWA2002617_HPP
# include <boost/python/object_core.hpp>
namespace boost { namespace python { namespace api {
# define BOOST_PYTHON_COMPARE_OP(op, opid) \
template <class L, class R> \
bool operator op(L const& l, R const& r) \
{ \
return PyObject_RichCompareBool(&*object(l), &*object(r), opid); \
}
BOOST_PYTHON_COMPARE_OP(>, Py_GT)
BOOST_PYTHON_COMPARE_OP(>=, Py_GE)
BOOST_PYTHON_COMPARE_OP(<, Py_LT)
BOOST_PYTHON_COMPARE_OP(<=, Py_LE)
BOOST_PYTHON_COMPARE_OP(==, Py_EQ)
BOOST_PYTHON_COMPARE_OP(!=, Py_NE)
# undef BOOST_PYTHON_COMPARE_OP
# define BOOST_PYTHON_BINARY_OPERATOR(op) \
BOOST_PYTHON_DECL object operator op(object const& l, object const& r); \
template <class L, class R> \
object operator op(L const& l, R const& r) \
{ \
return object(l) op object(r); \
}
BOOST_PYTHON_BINARY_OPERATOR(+)
BOOST_PYTHON_BINARY_OPERATOR(-)
BOOST_PYTHON_BINARY_OPERATOR(*)
BOOST_PYTHON_BINARY_OPERATOR(/)
BOOST_PYTHON_BINARY_OPERATOR(%)
BOOST_PYTHON_BINARY_OPERATOR(<<)
BOOST_PYTHON_BINARY_OPERATOR(>>)
BOOST_PYTHON_BINARY_OPERATOR(&)
BOOST_PYTHON_BINARY_OPERATOR(^)
BOOST_PYTHON_BINARY_OPERATOR(|)
# undef BOOST_PYTHON_BINARY_OPERATOR
# define BOOST_PYTHON_INPLACE_OPERATOR(op) \
BOOST_PYTHON_DECL object& operator op(object& l, object const& r); \
template <class R> \
object& operator op(object& l, R const& r) \
{ \
return l op object(r); \
}
BOOST_PYTHON_INPLACE_OPERATOR(+=)
BOOST_PYTHON_INPLACE_OPERATOR(-=)
BOOST_PYTHON_INPLACE_OPERATOR(*=)
BOOST_PYTHON_INPLACE_OPERATOR(/=)
BOOST_PYTHON_INPLACE_OPERATOR(%=)
BOOST_PYTHON_INPLACE_OPERATOR(<<=)
BOOST_PYTHON_INPLACE_OPERATOR(>>=)
BOOST_PYTHON_INPLACE_OPERATOR(&=)
BOOST_PYTHON_INPLACE_OPERATOR(^=)
BOOST_PYTHON_INPLACE_OPERATOR(|=)
# undef BOOST_PYTHON_INPLACE_OPERATOR
}}} // namespace boost::python
#endif // OBJECT_OPERATORS_DWA2002617_HPP

View File

@@ -8,12 +8,20 @@
namespace boost { namespace python {
class object;
namespace api
{
class object;
BOOST_PYTHON_DECL object getattr(object const& target, object const& key);
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value);
BOOST_PYTHON_DECL object getitem(object const& target, object const& key);
BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value);
BOOST_PYTHON_DECL object getattr(object const& target, object const& key);
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value);
BOOST_PYTHON_DECL object getitem(object const& target, object const& key);
BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value);
}
using api::getattr;
using api::setattr;
using api::getitem;
using api::setitem;
}} // namespace boost::python

View File

@@ -196,9 +196,12 @@ 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
@@ -300,6 +303,7 @@ namespace self_ns \
return detail::operator_<detail::op_##id>(); \
} \
}
# undef BOOST_PYTHON_INPLACE_OPERATOR
BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
@@ -310,7 +314,8 @@ 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)
# undef BOOST_PYTHON_UNARY_OPERATOR
}} // namespace boost::python
# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP

View File

@@ -6,10 +6,9 @@
#ifndef PROXY_DWA2002615_HPP
# define PROXY_DWA2002615_HPP
# include <boost/python/object_core.hpp>
# include <boost/python/object_operators.hpp>
namespace boost { namespace python {
class object;
namespace boost { namespace python { namespace api {
template <class Policies>
class proxy
@@ -23,37 +22,15 @@ class proxy
operator object() const;
// to support a[b] = c[d]
proxy& operator=(copy_ctor_self);
proxy const& operator=(copy_ctor_self) const;
template <class T>
inline proxy& operator=(T const& rhs)
inline proxy const& operator=(T const& rhs) const
{
Policies::set(m_target, m_key, python::object(rhs));
return *this;
}
# define BOOST_PYTHON_PROXY_ASSIGN_DECL(op) \
object operator op (object const&); \
\
template <class T> \
object operator op (T const& rhs) \
{ \
return *this op python::object(rhs); \
}
// BOOST_PYTHON_PROXY_ASSIGN_DECL(=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(+=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(-=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(*=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(/=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(%=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(<<=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(>>=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(&=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(^=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(|=)
# undef BOOST_PYTHON_PROXY_ASSIGN_DECL
// truth value testing
operator object::bool_type() const;
bool operator!() const; // needed for vc6
@@ -84,33 +61,29 @@ inline proxy<Policies>::operator object() const
// to support a[b] = c[d]
template <class Policies>
inline proxy<Policies>& proxy<Policies>::operator=(typename proxy::copy_ctor_self rhs)
inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::copy_ctor_self rhs) const
{
return *this = python::object(rhs);
}
# define BOOST_PYTHON_PROXY_ASSIGN_DEF(op) \
template <class Policies> \
inline object proxy<Policies>::operator op(object const& other) \
{ \
return Policies::set( \
m_target, m_key \
, Policies::get(m_target,m_key) op other); \
}
BOOST_PYTHON_PROXY_ASSIGN_DEF(+=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(-=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(*=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(/=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(%=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(<<=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(>>=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(&=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(^=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(|=)
# undef BOOST_PYTHON_PROXY_ASSIGN_DEF
# define BOOST_PYTHON_PROXY_INPLACE(op) \
template <class Policies, class R> \
proxy<Policies> const& operator op(proxy<Policies> const& lhs, R const& other) \
{ \
object old(lhs); \
return lhs = (old op other); \
}
BOOST_PYTHON_PROXY_INPLACE(+=)
BOOST_PYTHON_PROXY_INPLACE(-=)
BOOST_PYTHON_PROXY_INPLACE(*=)
BOOST_PYTHON_PROXY_INPLACE(/=)
BOOST_PYTHON_PROXY_INPLACE(%=)
BOOST_PYTHON_PROXY_INPLACE(<<=)
BOOST_PYTHON_PROXY_INPLACE(>>=)
BOOST_PYTHON_PROXY_INPLACE(&=)
BOOST_PYTHON_PROXY_INPLACE(^=)
BOOST_PYTHON_PROXY_INPLACE(|=)
# undef BOOST_PYTHON_PROXY_INPLACE
template <class Policies>
inline proxy<Policies>::operator object::bool_type() const
@@ -124,6 +97,6 @@ inline bool proxy<Policies>::operator!() const
return !python::object(*this);
}
}} // namespace boost::python
}}} // namespace boost::python::api
#endif // PROXY_DWA2002615_HPP