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