class_metadata.hpp 8.7 KB

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