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