Skip to content

Commit 913d298

Browse files
committed
Fixed object proxy chaining for everything bug GCC 2.9x
[SVN r14183]
1 parent e2d75c0 commit 913d298

7 files changed

Lines changed: 184 additions & 117 deletions

File tree

include/boost/python/object_attributes.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ struct attribute_policies : const_attribute_policies
2525
//
2626
// implementation
2727
//
28-
inline object_attribute object::attr(char const* name)
28+
template <class U>
29+
inline object_attribute object_operators<U>::attr(char const* name)
2930
{
30-
return object_attribute(*this, object(name));
31+
return object_attribute(*static_cast<U*>(this), object(name));
3132
}
3233

33-
inline const_object_attribute object::attr(char const* name) const
34+
template <class U>
35+
inline const_object_attribute object_operators<U>::attr(char const* name) const
3436
{
35-
return const_object_attribute(*this, object(name));
37+
return const_object_attribute(*static_cast<U const*>(this), object(name));
3638
}
3739

3840

include/boost/python/object_core.hpp

Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# include <boost/python/converter/arg_to_python.hpp>
1010
# include <boost/python/detail/preprocessor.hpp>
1111
# include <boost/python/call.hpp>
12+
# include <boost/preprocessor/max.hpp>
1213

1314
namespace boost { namespace python {
1415

@@ -32,7 +33,21 @@ namespace api
3233
typedef proxy<const_item_policies> const_object_item;
3334
typedef proxy<item_policies> object_item;
3435

35-
class object
36+
// A way to turn a conrete type T into a type dependent on U. This
37+
// keeps conforming compilers from complaining about returning an
38+
// incomplete T from a template member function (which must be
39+
// defined in the class body to keep MSVC happy).
40+
template <class T, class U>
41+
struct dependent
42+
{
43+
typedef T type;
44+
};
45+
46+
class object;
47+
typedef handle<> const& (object::*bool_type)() const;
48+
49+
template <class U>
50+
class object_operators
3651
{
3752
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
3853
typedef object const& self_cref;
@@ -41,63 +56,31 @@ namespace api
4156
# endif
4257

4358
public:
44-
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
45-
// copy constructor without NULL checking, for efficiency
46-
object(object const&);
47-
# endif
48-
49-
// explicit conversion from any C++ object to Python
50-
template <class T>
51-
explicit object(T const& x)
52-
: m_ptr(
53-
python::borrowed(
54-
python::allow_null( // null check is already done
55-
converter::arg_to_python<T>(x).get())
56-
)
57-
)
58-
{
59-
}
60-
61-
// capture this case explicitly to handle string
62-
// literals. Otherwise, they get deduced as char[N]const& above
63-
// and conversion fails at runtime.
64-
explicit object(char const* x)
65-
: m_ptr(
66-
python::borrowed(
67-
python::allow_null( // null check is already done
68-
converter::arg_to_python<char const*>(x).get())
69-
)
70-
)
71-
{
72-
}
73-
74-
// Throw error_already_set() if the handle is null.
75-
explicit object(handle<> const&);
76-
7759
// Attribute access via x.attr("attribute_name")
7860
const_object_attribute attr(char const*) const;
7961
object_attribute attr(char const*);
8062

81-
object operator()() const
82-
{
83-
return object(call<handle<> >(m_ptr.get()));
84-
}
63+
object operator()() const;
8564

8665
# ifndef BOOST_PYTHON_GENERATE_CODE
8766
# include <boost/python/preprocessed/object_call.hpp>
8867
# endif
8968

90-
# define BOOST_PYTHON_OBJECT_CALL(nargs,ignored) \
91-
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
92-
object operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
93-
{ \
94-
return object(call<handle<> >(&**this, BOOST_PP_ENUM_PARAMS(nargs, a))); \
69+
# define BOOST_PYTHON_OBJECT_CALL(nargs,ignored) \
70+
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
71+
typename dependent<object,A0>::type \
72+
operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
73+
{ \
74+
typedef typename dependent<object,A0>::type obj; \
75+
obj const& f = *static_cast<U const*>(this); \
76+
return call<obj>(f.ptr().get(), BOOST_PP_ENUM_PARAMS(nargs, a)); \
9577
}
9678

97-
BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_OBJECT_CALL, ignored)
79+
BOOST_PP_REPEAT_FROM_TO_2ND(
80+
BOOST_PP_MAX(1, BOOST_PYTHON_ARITY_START), BOOST_PYTHON_ARITY_FINISH
81+
, BOOST_PYTHON_OBJECT_CALL, ignored)
9882

9983
// truth value testing
100-
typedef handle<> (object::*bool_type);
10184
operator bool_type() const;
10285
bool operator!() const; // needed for vc6
10386

@@ -126,7 +109,50 @@ namespace api
126109
return (*this)[object(key)];
127110
}
128111
# endif
112+
113+
# if BOOST_MSVC == 1200
114+
// For whatever reason, VC6 generates incorrect code unless we
115+
// define this
116+
object_operators& operator=(object_operators const&) { return *this; }
117+
# endif
118+
};
119+
120+
class object : public object_operators<object>
121+
{
122+
public:
123+
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
124+
// copy constructor without NULL checking, for efficiency
125+
object(object const&);
126+
# endif
127+
128+
// explicit conversion from any C++ object to Python
129+
template <class T>
130+
explicit object(T const& x)
131+
: m_ptr(
132+
python::borrowed(
133+
python::allow_null( // null check is already done
134+
converter::arg_to_python<T>(x).get())
135+
)
136+
)
137+
{
138+
}
139+
140+
// capture this case explicitly to handle string
141+
// literals. Otherwise, they get deduced as char[N]const& above
142+
// and conversion fails at runtime.
143+
explicit object(char const* x)
144+
: m_ptr(
145+
python::borrowed(
146+
python::allow_null( // null check is already done
147+
converter::arg_to_python<char const*>(x).get())
148+
)
149+
)
150+
{
151+
}
129152

153+
// Throw error_already_set() if the handle is null.
154+
explicit object(handle<> const&);
155+
130156
// Underlying object access
131157
handle<> const& ptr() const;
132158

@@ -136,7 +162,7 @@ namespace api
136162
object(detail::borrowed<PyObject>*);
137163
class new_pyobject_reference;
138164
object(new_pyobject_reference*);
139-
165+
140166
private:
141167
handle<> m_ptr;
142168
};
@@ -232,16 +258,6 @@ inline handle<> const& object::ptr() const
232258
return m_ptr;
233259
}
234260

235-
inline object::operator object::bool_type() const
236-
{
237-
return PyObject_IsTrue(m_ptr.get()) ? &object::m_ptr : 0;
238-
}
239-
240-
inline bool object::operator!() const
241-
{
242-
return !PyObject_IsTrue(m_ptr.get());
243-
}
244-
245261
//
246262
// Converter speciaization implementations
247263
//

include/boost/python/object_items.hpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,33 @@ struct item_policies : const_item_policies
2525
//
2626
// implementation
2727
//
28-
inline object_item object::operator[](object::self_cref key)
28+
template <class U>
29+
inline object_item
30+
object_operators<U>::operator[](self_cref key)
2931
{
30-
return object_item(*this, key);
32+
return object_item(*static_cast<U*>(this), key);
3133
}
3234

33-
inline const_object_item object::operator[](object::self_cref key) const
35+
template <class U>
36+
inline const_object_item
37+
object_operators<U>::operator[](self_cref key) const
3438
{
35-
return const_object_item(*this, key);
39+
return const_object_item(*static_cast<U const*>(this), key);
3640
}
3741

3842
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
43+
template <class U>
3944
template <class T>
4045
inline const_object_item
41-
object::operator[](T const& key) const
46+
object_operators<U>::operator[](T const& key) const
4247
{
4348
return (*this)[object(key)];
4449
}
4550

51+
template <class U>
4652
template <class T>
4753
inline object_item
48-
object::operator[](T const& key)
54+
object_operators<U>::operator[](T const& key)
4955
{
5056
return (*this)[object(key)];
5157
}

include/boost/python/object_operators.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@
1010

1111
namespace boost { namespace python { namespace api {
1212

13+
template <class U>
14+
object object_operators<U>::operator()() const
15+
{
16+
object const& f = *static_cast<U const*>(this);
17+
return call<object>(f.ptr().get());
18+
}
19+
20+
21+
template <class U>
22+
inline
23+
object_operators<U>::operator bool_type() const
24+
{
25+
object const& x = *static_cast<U const*>(this);
26+
return PyObject_IsTrue(x.ptr().get()) ? &object::ptr : 0;
27+
}
28+
29+
template <class U>
30+
inline bool
31+
object_operators<U>::operator!() const
32+
{
33+
object const& x = *static_cast<U const*>(this);
34+
return !PyObject_IsTrue(x.ptr().get());
35+
}
36+
1337
# define BOOST_PYTHON_COMPARE_OP(op, opid) \
1438
template <class L, class R> \
1539
bool operator op(L const& l, R const& r) \

0 commit comments

Comments
 (0)