Skip to content

Commit 66f2cd8

Browse files
committed
object operator support
[SVN r14168]
1 parent 87bda9e commit 66f2cd8

15 files changed

Lines changed: 775 additions & 436 deletions

Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dll bpl
2828
src/converter/callback.cpp
2929
src/object/iterator.cpp
3030
src/object_protocol.cpp
31+
src/object_operators.cpp
3132
:
3233
$(BOOST_PYTHON_V2_PROPERTIES)
3334
<define>BOOST_PYTHON_SOURCE

include/boost/python/converter/object_manager.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
# include <boost/mpl/select_type.hpp>
1313
# include <boost/python/detail/indirect_traits.hpp>
1414

15-
namespace boost { namespace python {
15+
namespace boost { namespace python { namespace api {
1616

1717
class object;
1818

19-
}}
19+
}}}
2020

2121
namespace boost { namespace python { namespace converter {
2222

@@ -142,7 +142,7 @@ inline T* get_managed_object(python::detail::borrowed<T> const volatile* p)
142142

143143
// forward declaration needed because name lookup is bound by the
144144
// definition context.
145-
PyObject* get_managed_object(python::object const&);
145+
PyObject* get_managed_object(python::api::object const&);
146146

147147
}}} // namespace boost::python::converter
148148

include/boost/python/object.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# include <boost/python/object_core.hpp>
1010
# include <boost/python/object_attributes.hpp>
1111
# include <boost/python/object_items.hpp>
12+
# include <boost/python/object_operators.hpp>
1213

1314
namespace boost { namespace python {
1415

include/boost/python/object_attributes.hpp

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,51 +10,48 @@
1010
# include <boost/python/object_core.hpp>
1111
# include <boost/python/object_protocol.hpp>
1212

13-
namespace boost { namespace python {
13+
namespace boost { namespace python { namespace api {
1414

15-
namespace detail
15+
struct const_attribute_policies
1616
{
17-
struct const_attribute_policies
18-
{
19-
static object get(object const& target, object const& key);
20-
};
17+
static object get(object const& target, object const& key);
18+
};
2119

22-
struct attribute_policies : const_attribute_policies
23-
{
24-
static object const& set(object const& target, object const& key, object const& value);
25-
};
26-
}
20+
struct attribute_policies : const_attribute_policies
21+
{
22+
static object const& set(object const& target, object const& key, object const& value);
23+
};
2724

2825
//
2926
// implementation
3027
//
31-
inline object_attribute object::_(char const* name)
28+
inline object_attribute object::attr(char const* name)
3229
{
3330
return object_attribute(*this, object(name));
3431
}
3532

36-
inline const_object_attribute object::_(char const* name) const
33+
inline const_object_attribute object::attr(char const* name) const
3734
{
3835
return const_object_attribute(*this, object(name));
3936
}
4037

41-
namespace detail
38+
39+
inline object const_attribute_policies::get(object const& target, object const& key)
4240
{
43-
inline object const_attribute_policies::get(object const& target, object const& key)
44-
{
45-
return python::getattr(target, key);
46-
}
41+
return python::getattr(target, key);
42+
}
4743

48-
inline object const& attribute_policies::set(
49-
object const& target
50-
, object const& key
51-
, object const& value)
52-
{
53-
python::setattr(target, key, value);
54-
return value;
55-
}
44+
inline object const& attribute_policies::set(
45+
object const& target
46+
, object const& key
47+
, object const& value)
48+
{
49+
python::setattr(target, key, value);
50+
return value;
5651
}
5752

53+
} // namespace api
54+
5855
namespace converter
5956
{
6057
// These specializations are a lie; the proxies do not directly
@@ -64,13 +61,13 @@ namespace converter
6461
// actually managing the object during the duration of the
6562
// conversion.
6663
template <>
67-
struct is_object_manager<object_attribute>
64+
struct is_object_manager<api::object_attribute>
6865
{
6966
BOOST_STATIC_CONSTANT(bool, value = true);
7067
};
7168

7269
template <>
73-
struct is_object_manager<const_object_attribute>
70+
struct is_object_manager<api::const_object_attribute>
7471
{
7572
BOOST_STATIC_CONSTANT(bool, value = true);
7673
};

include/boost/python/object_core.hpp

Lines changed: 112 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -12,122 +12,147 @@
1212

1313
namespace boost { namespace python {
1414

15+
// Put this in an inner namespace so that the generalized operators won't take over
16+
namespace api
17+
{
18+
1519
// This file contains the definition of the object class and enough to
1620
// construct/copy it, but not enough to do operations like
1721
// attribute/item access or addition.
1822

19-
template <class Policies> class proxy;
20-
namespace detail
21-
{
23+
template <class Policies> class proxy;
24+
2225
struct const_attribute_policies;
2326
struct attribute_policies;
2427
struct const_item_policies;
2528
struct item_policies;
26-
}
27-
typedef proxy<detail::const_attribute_policies> const_object_attribute;
28-
typedef proxy<detail::attribute_policies> object_attribute;
29-
typedef proxy<detail::const_item_policies> const_object_item;
30-
typedef proxy<detail::item_policies> object_item;
3129

32-
class object
33-
{
30+
typedef proxy<const_attribute_policies> const_object_attribute;
31+
typedef proxy<attribute_policies> object_attribute;
32+
typedef proxy<const_item_policies> const_object_item;
33+
typedef proxy<item_policies> object_item;
34+
35+
// A way to turn a conrete type T into a type dependent on U. This
36+
// keeps conforming compilers from complaining about returning an
37+
// incomplete T from a template member function (which must be
38+
// defined in the class body to keep MSVC happy).
39+
template <class T, class U>
40+
struct dependent
41+
{
42+
typedef T type;
43+
};
44+
45+
class object
46+
{
3447
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
35-
typedef object const& self_cref;
48+
typedef object const& self_cref;
3649
# else
37-
typedef object self_cref;
50+
typedef object self_cref;
3851
# endif
39-
public:
52+
public:
4053
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
41-
// copy constructor without NULL checking, for efficiency
42-
object(object const&);
54+
// copy constructor without NULL checking, for efficiency
55+
object(object const&);
4356
# endif
4457

45-
// explicit conversion from any C++ object to Python
46-
template <class T>
47-
explicit object(T const& x)
48-
: m_ptr(
49-
python::borrowed(
50-
python::allow_null( // null check is already done
51-
converter::arg_to_python<T>(x).get())
52-
)
53-
)
54-
{
55-
}
56-
57-
// capture this case explicitly to handle string
58-
// literals. Otherwise, they get deduced as char[N]const& above
59-
// and conversion fails at runtime.
60-
explicit object(char const* x)
61-
: m_ptr(
62-
python::borrowed(
63-
python::allow_null( // null check is already done
64-
converter::arg_to_python<char const*>(x).get())
65-
)
66-
)
67-
{
58+
// explicit conversion from any C++ object to Python
59+
template <class T>
60+
explicit object(T const& x)
61+
: m_ptr(
62+
python::borrowed(
63+
python::allow_null( // null check is already done
64+
converter::arg_to_python<T>(x).get())
65+
)
66+
)
67+
{
68+
}
69+
70+
// capture this case explicitly to handle string
71+
// literals. Otherwise, they get deduced as char[N]const& above
72+
// and conversion fails at runtime.
73+
explicit object(char const* x)
74+
: m_ptr(
75+
python::borrowed(
76+
python::allow_null( // null check is already done
77+
converter::arg_to_python<char const*>(x).get())
78+
)
79+
)
80+
{
6881

69-
}
82+
}
7083

71-
// Throw error_already_set() if the handle is null.
72-
explicit object(handle<> const&);
84+
// Throw error_already_set() if the handle is null.
85+
explicit object(handle<> const&);
7386

74-
// Attribute access via x._("attribute_name")
75-
const_object_attribute _(char const*) const;
76-
object_attribute _(char const*);
87+
// Attribute access via x.attr("attribute_name")
88+
const_object_attribute attr(char const*) const;
89+
object_attribute attr(char const*);
7790

78-
object operator()() const
79-
{
80-
return object(call<handle<> >(m_ptr.get()));
81-
}
91+
object operator()() const
92+
{
93+
return object(call<handle<> >(m_ptr.get()));
94+
}
8295

8396
# ifndef BOOST_PYTHON_GENERATE_CODE
8497
# include <boost/python/preprocessed/object_call.hpp>
8598
# endif
8699

87100
# define BOOST_PYTHON_OBJECT_CALL(nargs,ignored) \
88-
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
89-
object operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
90-
{ \
91-
return object(call<handle<> >(&**this, BOOST_PP_ENUM_PARAMS(nargs, a))); \
92-
}
93-
94-
BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_OBJECT_CALL, ignored)
95-
96-
// truth value testing
97-
typedef handle<> (object::*bool_type);
98-
operator bool_type() const;
99-
bool operator!() const; // needed for vc6
100-
101-
// item access
102-
const_object_item operator[](self_cref) const;
103-
object_item operator[](self_cref);
101+
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
102+
object operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
103+
{ \
104+
return object(call<handle<> >(&**this, BOOST_PP_ENUM_PARAMS(nargs, a))); \
105+
}
106+
107+
BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_OBJECT_CALL, ignored)
108+
109+
// truth value testing
110+
typedef handle<> (object::*bool_type);
111+
operator bool_type() const;
112+
bool operator!() const; // needed for vc6
113+
114+
// item access
115+
const_object_item operator[](self_cref) const;
116+
object_item operator[](self_cref);
104117

105-
template <class T>
106-
const_object_item operator[](T const& key) const
107-
{
108-
return (*this)[object(key)];
109-
}
118+
template <class T>
119+
# if BOOST_MSVC != 1300
120+
typename dependent<const_object_item,T>::type
121+
# else
122+
const_object_item
123+
# endif
124+
operator[](T const& key) const
125+
{
126+
return (*this)[object(key)];
127+
}
110128

111-
template <class T>
112-
object_item operator[](T const& key)
113-
{
114-
return (*this)[object(key)];
115-
}
129+
template <class T>
130+
# if BOOST_MSVC != 1300
131+
typename dependent<object_item,T>::type
132+
# else
133+
object_item
134+
# endif
135+
operator[](T const& key)
136+
{
137+
return (*this)[object(key)];
138+
}
116139

117-
// Underlying object access
118-
PyObject* operator->() const;
119-
PyObject& operator*() const;
120-
121-
public: // implementation detail -- for internal use only
122-
object(null_ok<detail::borrowed<PyObject> >*);
123-
object(detail::borrowed<null_ok<PyObject> >*);
124-
object(detail::borrowed<PyObject>*);
125-
class new_pyobject_reference;
126-
object(new_pyobject_reference*);
140+
// Underlying object access
141+
PyObject* operator->() const;
142+
PyObject& operator*() const;
143+
144+
public: // implementation detail -- for internal use only
145+
object(null_ok<detail::borrowed<PyObject> >*);
146+
object(detail::borrowed<null_ok<PyObject> >*);
147+
object(detail::borrowed<PyObject>*);
148+
class new_pyobject_reference;
149+
object(new_pyobject_reference*);
127150

128-
private:
129-
handle<> m_ptr;
130-
};
151+
private:
152+
handle<> m_ptr;
153+
};
154+
}
155+
using api::object;
131156

132157
//
133158
// Converter Specializations

0 commit comments

Comments
 (0)