1010# include < boost/python/detail/preprocessor.hpp>
1111# include < boost/python/call.hpp>
1212# include < boost/preprocessor/max.hpp>
13+ # include < boost/python/slice_nil.hpp>
14+ # include < boost/type.hpp>
1315
1416namespace boost { namespace python {
1517
@@ -27,12 +29,74 @@ namespace api
2729 struct attribute_policies ;
2830 struct const_item_policies ;
2931 struct item_policies ;
32+ struct const_slice_policies ;
33+ struct slice_policies ;
3034
3135 typedef proxy<const_attribute_policies> const_object_attribute;
3236 typedef proxy<attribute_policies> object_attribute;
3337 typedef proxy<const_item_policies> const_object_item;
3438 typedef proxy<item_policies> object_item;
39+ typedef proxy<const_slice_policies> const_object_slice;
40+ typedef proxy<slice_policies> object_slice;
41+
42+ //
43+ // is_proxy -- proxy type detection
44+ //
45+ # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
46+ template <class T >
47+ struct is_proxy
48+ {
49+ BOOST_STATIC_CONSTANT (bool , value = false );
50+ };
51+ template <class T >
52+ struct is_proxy <proxy<T> >
53+ {
54+ BOOST_STATIC_CONSTANT (bool , value = true );
55+ };
56+ # else
57+ typedef char yes_proxy;
58+ typedef char (&no_proxy)[2];
59+ template <class T >
60+ yes_proxy is_proxy_helper (boost::type<proxy<T> >*);
61+ no_proxy is_proxy_helper (...);
62+ template <class T >
63+ struct is_proxy
64+ {
65+ BOOST_STATIC_CONSTANT (
66+ bool , value = (sizeof (is_proxy_helper((boost::type<T>*)0 ))
67+ == sizeof (yes_proxy)));
68+ };
69+ # endif
3570
71+ //
72+ // object_handle -- get the handle to construct the object with,
73+ // based on whether T is a proxy or not
74+ //
75+ template <bool = false >
76+ struct object_handle
77+ {
78+ template <class T >
79+ static handle<> get (T const & x)
80+ {
81+ return handle<>(
82+ python::borrowed (
83+ python::allow_null ( // null check is already done
84+ converter::arg_to_python<T>(x).get ())
85+ )
86+ );
87+ }
88+ };
89+
90+ template <>
91+ struct object_handle <true >
92+ {
93+ template <class Policies >
94+ static handle<> get (proxy<Policies> const & x)
95+ {
96+ return x.operator object ().ptr ();
97+ }
98+ };
99+
36100 // A way to turn a conrete type T into a type dependent on U. This
37101 // keeps conforming compilers from complaining about returning an
38102 // incomplete T from a template member function (which must be
@@ -54,12 +118,19 @@ namespace api
54118# else
55119 typedef object self_cref;
56120# endif
121+
122+ // there appears to be a codegen bug here. We prevent the early
123+ // destruction of a temporary in CWPro8 by binding a named
124+ // object instead.
125+ # if __MWERKS__ != 0x3000
126+ typedef object const & object_cref;
127+ # else
128+ typedef object const object_cref;
129+ # endif
57130
58131 public:
59- // Attribute access via x.attr("attribute_name")
60- const_object_attribute attr (char const *) const ;
61- object_attribute attr (char const *);
62-
132+ // function call
133+ //
63134 object operator ()() const ;
64135
65136# ifndef BOOST_PYTHON_GENERATE_CODE
@@ -81,10 +152,17 @@ namespace api
81152 , BOOST_PYTHON_OBJECT_CALL, ignored)
82153
83154 // truth value testing
155+ //
84156 operator bool_type() const ;
85157 bool operator !() const ; // needed for vc6
86158
159+ // Attribute access
160+ //
161+ const_object_attribute attr (char const *) const ;
162+ object_attribute attr (char const *);
163+
87164 // item access
165+ //
88166 const_object_item operator [](self_cref) const ;
89167 object_item operator [](self_cref);
90168
@@ -110,6 +188,47 @@ namespace api
110188 }
111189# endif
112190
191+ // slicing
192+ //
193+ const_object_slice slice (self_cref, self_cref) const ;
194+ object_slice slice (self_cref, self_cref);
195+
196+ const_object_slice slice (slice_nil, self_cref) const ;
197+ object_slice slice (slice_nil, self_cref);
198+
199+ const_object_slice slice (self_cref, slice_nil) const ;
200+ object_slice slice (self_cref, slice_nil);
201+
202+ # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
203+ template <class T , class V >
204+ const_object_slice
205+ slice (T const & start, V const & end) const ;
206+
207+ template <class T , class V >
208+ object_slice
209+ slice (T const & start, V const & end);
210+
211+ # else
212+ template <class T , class V >
213+ const_object_slice
214+ slice (T const & start, V const & end) const
215+ {
216+ return this ->slice (
217+ slice_bound<T>::type (start)
218+ , slice_bound<V>::type (end));
219+ }
220+
221+ template <class T , class V >
222+ object_slice
223+ slice (T const & start, V const & end)
224+ {
225+ return this ->slice (
226+ slice_bound<T>::type (start)
227+ , slice_bound<V>::type (end));
228+ }
229+ # endif
230+
231+
113232# if BOOST_MSVC == 1200
114233 // For whatever reason, VC6 generates incorrect code unless we
115234 // define this
@@ -128,25 +247,15 @@ namespace api
128247 // explicit conversion from any C++ object to Python
129248 template <class T >
130249 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- )
250+ : m_ptr(object_handle<is_proxy<T>::value>::get(x))
137251 {
138252 }
139253
140254 // capture this case explicitly to handle string
141255 // literals. Otherwise, they get deduced as char[N]const& above
142256 // and conversion fails at runtime.
143257 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- )
258+ : m_ptr(object_handle<>::get(x))
150259 {
151260 }
152261
0 commit comments