Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/python/converter/object_manager.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // Copyright David Abrahams 2002. | |
2 // Distributed under the Boost Software License, Version 1.0. (See | |
3 // accompanying file LICENSE_1_0.txt or copy at | |
4 // http://www.boost.org/LICENSE_1_0.txt) | |
5 #ifndef OBJECT_MANAGER_DWA2002614_HPP | |
6 # define OBJECT_MANAGER_DWA2002614_HPP | |
7 | |
8 # include <boost/python/handle.hpp> | |
9 # include <boost/python/cast.hpp> | |
10 # include <boost/python/converter/pyobject_traits.hpp> | |
11 # include <boost/type_traits/object_traits.hpp> | |
12 # include <boost/mpl/if.hpp> | |
13 # include <boost/python/detail/indirect_traits.hpp> | |
14 # include <boost/mpl/bool.hpp> | |
15 | |
16 // Facilities for dealing with types which always manage Python | |
17 // objects. Some examples are object, list, str, et. al. Different | |
18 // to_python/from_python conversion rules apply here because in | |
19 // contrast to other types which are typically embedded inside a | |
20 // Python object, these are wrapped around a Python object. For most | |
21 // object managers T, a C++ non-const T reference argument does not | |
22 // imply the existence of a T lvalue embedded in the corresponding | |
23 // Python argument, since mutating member functions on T actually only | |
24 // modify the held Python object. | |
25 // | |
26 // handle<T> is an object manager, though strictly speaking it should | |
27 // not be. In other words, even though mutating member functions of | |
28 // hanlde<T> actually modify the handle<T> and not the T object, | |
29 // handle<T>& arguments of wrapped functions will bind to "rvalues" | |
30 // wrapping the actual Python argument, just as with other object | |
31 // manager classes. Making an exception for handle<T> is simply not | |
32 // worth the trouble. | |
33 // | |
34 // borrowed<T> cv* is an object manager so that we can use the general | |
35 // to_python mechanisms to convert raw Python object pointers to | |
36 // python, without the usual semantic problems of using raw pointers. | |
37 | |
38 | |
39 // Object Manager Concept requirements: | |
40 // | |
41 // T is an Object Manager | |
42 // p is a PyObject* | |
43 // x is a T | |
44 // | |
45 // * object_manager_traits<T>::is_specialized == true | |
46 // | |
47 // * T(detail::borrowed_reference(p)) | |
48 // Manages p without checking its type | |
49 // | |
50 // * get_managed_object(x, boost::python::tag) | |
51 // Convertible to PyObject* | |
52 // | |
53 // Additional requirements if T can be converted from_python: | |
54 // | |
55 // * T(object_manager_traits<T>::adopt(p)) | |
56 // steals a reference to p, or throws a TypeError exception if | |
57 // p doesn't have an appropriate type. May assume p is non-null | |
58 // | |
59 // * X::check(p) | |
60 // convertible to bool. True iff T(X::construct(p)) will not | |
61 // throw. | |
62 | |
63 // Forward declarations | |
64 // | |
65 namespace boost { namespace python | |
66 { | |
67 namespace api | |
68 { | |
69 class object; | |
70 } | |
71 }} | |
72 | |
73 namespace boost { namespace python { namespace converter { | |
74 | |
75 | |
76 // Specializations for handle<T> | |
77 template <class T> | |
78 struct handle_object_manager_traits | |
79 : pyobject_traits<typename T::element_type> | |
80 { | |
81 private: | |
82 typedef pyobject_traits<typename T::element_type> base; | |
83 | |
84 public: | |
85 BOOST_STATIC_CONSTANT(bool, is_specialized = true); | |
86 | |
87 // Initialize with a null_ok pointer for efficiency, bypassing the | |
88 // null check since the source is always non-null. | |
89 static null_ok<typename T::element_type>* adopt(PyObject* p) | |
90 { | |
91 return python::allow_null(base::checked_downcast(p)); | |
92 } | |
93 }; | |
94 | |
95 template <class T> | |
96 struct default_object_manager_traits | |
97 { | |
98 BOOST_STATIC_CONSTANT( | |
99 bool, is_specialized = python::detail::is_borrowed_ptr<T>::value | |
100 ); | |
101 }; | |
102 | |
103 template <class T> | |
104 struct object_manager_traits | |
105 : mpl::if_c< | |
106 is_handle<T>::value | |
107 , handle_object_manager_traits<T> | |
108 , default_object_manager_traits<T> | |
109 >::type | |
110 { | |
111 }; | |
112 | |
113 // | |
114 // Traits for detecting whether a type is an object manager or a | |
115 // (cv-qualified) reference to an object manager. | |
116 // | |
117 | |
118 template <class T> | |
119 struct is_object_manager | |
120 : mpl::bool_<object_manager_traits<T>::is_specialized> | |
121 { | |
122 }; | |
123 | |
124 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
125 template <class T> | |
126 struct is_reference_to_object_manager | |
127 : mpl::false_ | |
128 { | |
129 }; | |
130 | |
131 template <class T> | |
132 struct is_reference_to_object_manager<T&> | |
133 : is_object_manager<T> | |
134 { | |
135 }; | |
136 | |
137 template <class T> | |
138 struct is_reference_to_object_manager<T const&> | |
139 : is_object_manager<T> | |
140 { | |
141 }; | |
142 | |
143 template <class T> | |
144 struct is_reference_to_object_manager<T volatile&> | |
145 : is_object_manager<T> | |
146 { | |
147 }; | |
148 | |
149 template <class T> | |
150 struct is_reference_to_object_manager<T const volatile&> | |
151 : is_object_manager<T> | |
152 { | |
153 }; | |
154 # else | |
155 | |
156 namespace detail | |
157 { | |
158 typedef char (&yes_reference_to_object_manager)[1]; | |
159 typedef char (&no_reference_to_object_manager)[2]; | |
160 | |
161 // A number of nastinesses go on here in order to work around MSVC6 | |
162 // bugs. | |
163 template <class T> | |
164 struct is_object_manager_help | |
165 { | |
166 typedef typename mpl::if_< | |
167 is_object_manager<T> | |
168 , yes_reference_to_object_manager | |
169 , no_reference_to_object_manager | |
170 >::type type; | |
171 | |
172 // If we just use the type instead of the result of calling this | |
173 // function, VC6 will ICE. | |
174 static type call(); | |
175 }; | |
176 | |
177 // A set of overloads for each cv-qualification. The same argument | |
178 // is passed twice: the first one is used to unwind the cv*, and the | |
179 // second one is used to avoid relying on partial ordering for | |
180 // overload resolution. | |
181 template <class U> | |
182 typename is_object_manager_help<U> | |
183 is_object_manager_helper(U*, void*); | |
184 | |
185 template <class U> | |
186 typename is_object_manager_help<U> | |
187 is_object_manager_helper(U const*, void const*); | |
188 | |
189 template <class U> | |
190 typename is_object_manager_help<U> | |
191 is_object_manager_helper(U volatile*, void volatile*); | |
192 | |
193 template <class U> | |
194 typename is_object_manager_help<U> | |
195 is_object_manager_helper(U const volatile*, void const volatile*); | |
196 | |
197 template <class T> | |
198 struct is_reference_to_object_manager_nonref | |
199 : mpl::false_ | |
200 { | |
201 }; | |
202 | |
203 template <class T> | |
204 struct is_reference_to_object_manager_ref | |
205 { | |
206 static T sample_object; | |
207 BOOST_STATIC_CONSTANT( | |
208 bool, value | |
209 = (sizeof(is_object_manager_helper(&sample_object, &sample_object).call()) | |
210 == sizeof(detail::yes_reference_to_object_manager) | |
211 ) | |
212 ); | |
213 typedef mpl::bool_<value> type; | |
214 }; | |
215 } | |
216 | |
217 template <class T> | |
218 struct is_reference_to_object_manager | |
219 : mpl::if_< | |
220 is_reference<T> | |
221 , detail::is_reference_to_object_manager_ref<T> | |
222 , detail::is_reference_to_object_manager_nonref<T> | |
223 >::type | |
224 { | |
225 }; | |
226 # endif | |
227 | |
228 }}} // namespace boost::python::converter | |
229 | |
230 #endif // OBJECT_MANAGER_DWA2002614_HPP |