]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/python/include/boost/python/object/class_metadata.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / python / include / boost / python / object / class_metadata.hpp
1 // Copyright David Abrahams 2004.
2 // Copyright Stefan Seefeld 2016.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef boost_python_object_class_metadata_hpp_
8 #define boost_python_object_class_metadata_hpp_
9
10 #include <boost/python/converter/shared_ptr_from_python.hpp>
11 #include <boost/python/object/inheritance.hpp>
12 #include <boost/python/object/class_wrapper.hpp>
13 #include <boost/python/object/make_instance.hpp>
14 #include <boost/python/object/value_holder.hpp>
15 #include <boost/python/object/pointer_holder.hpp>
16 #include <boost/python/object/make_ptr_instance.hpp>
17
18 #include <boost/python/detail/force_instantiate.hpp>
19 #include <boost/python/detail/not_specified.hpp>
20
21 #include <boost/python/has_back_reference.hpp>
22 #include <boost/python/bases.hpp>
23
24 #include <boost/type_traits/add_pointer.hpp>
25 #include <boost/type_traits/is_convertible.hpp>
26 #include <boost/type_traits/is_polymorphic.hpp>
27
28 #include <boost/mpl/if.hpp>
29 #include <boost/mpl/eval_if.hpp>
30 #include <boost/mpl/bool.hpp>
31 #include <boost/mpl/or.hpp>
32 #include <boost/mpl/identity.hpp>
33 #include <boost/mpl/for_each.hpp>
34 #include <boost/mpl/placeholders.hpp>
35 #include <boost/mpl/single_view.hpp>
36
37 #include <boost/mpl/assert.hpp>
38 #include <boost/type_traits/is_same.hpp>
39
40 #include <boost/type_traits/is_convertible.hpp>
41
42 #include <boost/noncopyable.hpp>
43 #include <boost/detail/workaround.hpp>
44
45 namespace boost { namespace python { namespace objects {
46
47 BOOST_PYTHON_DECL
48 void copy_class_object(type_info const& src, type_info const& dst);
49
50 //
51 // Support for registering base/derived relationships
52 //
53 template <class Derived>
54 struct register_base_of
55 {
56 template <class Base>
57 inline void operator()(Base*) const
58 {
59 BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
60
61 // Register the Base class
62 register_dynamic_id<Base>();
63
64 // Register the up-cast
65 register_conversion<Derived,Base>(false);
66
67 // Register the down-cast, if appropriate.
68 this->register_downcast((Base*)0, is_polymorphic<Base>());
69 }
70
71 private:
72 static inline void register_downcast(void*, mpl::false_) {}
73
74 template <class Base>
75 static inline void register_downcast(Base*, mpl::true_)
76 {
77 register_conversion<Base, Derived>(true);
78 }
79
80 };
81
82 //
83 // Preamble of register_class. Also used for callback classes, which
84 // need some registration of their own.
85 //
86
87 template <class T, class Bases>
88 inline void register_shared_ptr_from_python_and_casts(T*, Bases)
89 {
90 // Constructor performs registration
91 python::detail::force_instantiate(converter::shared_ptr_from_python<T, boost::shared_ptr>());
92 #if __cplusplus >= 201103L
93 python::detail::force_instantiate(converter::shared_ptr_from_python<T, std::shared_ptr>());
94 #endif
95
96 //
97 // register all up/downcasts here. We're using the alternate
98 // interface to mpl::for_each to avoid an MSVC 6 bug.
99 //
100 register_dynamic_id<T>();
101 mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0);
102 }
103
104 //
105 // Helper for choosing the unnamed held_type argument
106 //
107 template <class T, class Prev>
108 struct select_held_type
109 : mpl::if_<
110 mpl::or_<
111 python::detail::specifies_bases<T>
112 , is_same<T,noncopyable>
113 >
114 , Prev
115 , T
116 >
117 {
118 };
119
120 template <
121 class T // class being wrapped
122 , class X1 // = detail::not_specified
123 , class X2 // = detail::not_specified
124 , class X3 // = detail::not_specified
125 >
126 struct class_metadata
127 {
128 //
129 // Calculate the unnamed template arguments
130 //
131
132 // held_type_arg -- not_specified, [a class derived from] T or a
133 // smart pointer to [a class derived from] T. Preserving
134 // not_specified allows us to give class_<T,T> a back-reference.
135 typedef typename select_held_type<
136 X1
137 , typename select_held_type<
138 X2
139 , typename select_held_type<
140 X3
141 , python::detail::not_specified
142 >::type
143 >::type
144 >::type held_type_arg;
145
146 // bases
147 typedef typename python::detail::select_bases<
148 X1
149 , typename python::detail::select_bases<
150 X2
151 , typename python::detail::select_bases<
152 X3
153 , python::bases<>
154 >::type
155 >::type
156 >::type bases;
157
158 typedef mpl::or_<
159 is_same<X1,noncopyable>
160 , is_same<X2,noncopyable>
161 , is_same<X3,noncopyable>
162 > is_noncopyable;
163
164 //
165 // Holder computation.
166 //
167
168 // Compute the actual type that will be held in the Holder.
169 typedef typename mpl::if_<
170 is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg
171 >::type held_type;
172
173 // Determine if the object will be held by value
174 typedef mpl::bool_<is_convertible<held_type*,T*>::value> use_value_holder;
175
176 // Compute the "wrapped type", that is, if held_type is a smart
177 // pointer, we're talking about the pointee.
178 typedef typename mpl::eval_if<
179 use_value_holder
180 , mpl::identity<held_type>
181 , pointee<held_type>
182 >::type wrapped;
183
184 // Determine whether to use a "back-reference holder"
185 typedef mpl::bool_<
186 mpl::or_<
187 has_back_reference<T>
188 , is_same<held_type_arg,T>
189 , is_base_and_derived<T,wrapped>
190 >::value
191 > use_back_reference;
192
193 // Select the holder.
194 typedef typename mpl::eval_if<
195 use_back_reference
196 , mpl::if_<
197 use_value_holder
198 , value_holder_back_reference<T, wrapped>
199 , pointer_holder_back_reference<held_type,T>
200 >
201 , mpl::if_<
202 use_value_holder
203 , value_holder<T>
204 , pointer_holder<held_type,wrapped>
205 >
206 >::type holder;
207
208 inline static void register_() // Register the runtime metadata.
209 {
210 class_metadata::register_aux((T*)0);
211 }
212
213 private:
214 template <class T2>
215 inline static void register_aux(python::wrapper<T2>*)
216 {
217 typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback;
218 class_metadata::register_aux2((T2*)0, use_callback());
219 }
220
221 inline static void register_aux(void*)
222 {
223 typedef typename is_base_and_derived<T,wrapped>::type use_callback;
224 class_metadata::register_aux2((T*)0, use_callback());
225 }
226
227 template <class T2, class Callback>
228 inline static void register_aux2(T2*, Callback)
229 {
230 objects::register_shared_ptr_from_python_and_casts((T2*)0, bases());
231 class_metadata::maybe_register_callback_class((T2*)0, Callback());
232
233 class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable());
234
235 class_metadata::maybe_register_pointer_to_python(
236 (T2*)0, (use_value_holder*)0, (use_back_reference*)0);
237 }
238
239
240 //
241 // Support for converting smart pointers to python
242 //
243 inline static void maybe_register_pointer_to_python(...) {}
244
245 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
246 inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*)
247 {
248 objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >());
249 objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
250 }
251 #endif
252
253 template <class T2>
254 inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*)
255 {
256 python::detail::force_instantiate(
257 objects::class_value_wrapper<
258 held_type
259 , make_ptr_instance<T2, pointer_holder<held_type, T2> >
260 >()
261 );
262 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
263 // explicit qualification of type_id makes msvc6 happy
264 objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
265 #endif
266 }
267 //
268 // Support for registering to-python converters
269 //
270 inline static void maybe_register_class_to_python(void*, mpl::true_) {}
271
272
273 template <class T2>
274 inline static void maybe_register_class_to_python(T2*, mpl::false_)
275 {
276 python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >());
277 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
278 // explicit qualification of type_id makes msvc6 happy
279 objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
280 #endif
281 }
282
283 //
284 // Support for registering callback classes
285 //
286 inline static void maybe_register_callback_class(void*, mpl::false_) {}
287
288 template <class T2>
289 inline static void maybe_register_callback_class(T2*, mpl::true_)
290 {
291 objects::register_shared_ptr_from_python_and_casts(
292 (wrapped*)0, mpl::single_view<T2>());
293 // explicit qualification of type_id makes msvc6 happy
294 objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>());
295 }
296 };
297
298 }}} // namespace boost::python::object
299
300 #endif