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