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
1314namespace 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//
0 commit comments