object_manager.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. # include <boost/python/handle.hpp>
  8. # include <boost/python/cast.hpp>
  9. # include <boost/python/converter/pyobject_traits.hpp>
  10. # include <boost/type_traits/object_traits.hpp>
  11. # include <boost/mpl/if.hpp>
  12. # include <boost/python/detail/indirect_traits.hpp>
  13. # include <boost/mpl/bool.hpp>
  14. // Facilities for dealing with types which always manage Python
  15. // objects. Some examples are object, list, str, et. al. Different
  16. // to_python/from_python conversion rules apply here because in
  17. // contrast to other types which are typically embedded inside a
  18. // Python object, these are wrapped around a Python object. For most
  19. // object managers T, a C++ non-const T reference argument does not
  20. // imply the existence of a T lvalue embedded in the corresponding
  21. // Python argument, since mutating member functions on T actually only
  22. // modify the held Python object.
  23. //
  24. // handle<T> is an object manager, though strictly speaking it should
  25. // not be. In other words, even though mutating member functions of
  26. // hanlde<T> actually modify the handle<T> and not the T object,
  27. // handle<T>& arguments of wrapped functions will bind to "rvalues"
  28. // wrapping the actual Python argument, just as with other object
  29. // manager classes. Making an exception for handle<T> is simply not
  30. // worth the trouble.
  31. //
  32. // borrowed<T> cv* is an object manager so that we can use the general
  33. // to_python mechanisms to convert raw Python object pointers to
  34. // python, without the usual semantic problems of using raw pointers.
  35. // Object Manager Concept requirements:
  36. //
  37. // T is an Object Manager
  38. // p is a PyObject*
  39. // x is a T
  40. //
  41. // * object_manager_traits<T>::is_specialized == true
  42. //
  43. // * T(detail::borrowed_reference(p))
  44. // Manages p without checking its type
  45. //
  46. // * get_managed_object(x, boost::python::tag)
  47. // Convertible to PyObject*
  48. //
  49. // Additional requirements if T can be converted from_python:
  50. //
  51. // * T(object_manager_traits<T>::adopt(p))
  52. // steals a reference to p, or throws a TypeError exception if
  53. // p doesn't have an appropriate type. May assume p is non-null
  54. //
  55. // * X::check(p)
  56. // convertible to bool. True iff T(X::construct(p)) will not
  57. // throw.
  58. // Forward declarations
  59. //
  60. namespace boost { namespace python
  61. {
  62. namespace api
  63. {
  64. class object;
  65. }
  66. }}
  67. namespace boost { namespace python { namespace converter {
  68. // Specializations for handle<T>
  69. template <class T>
  70. struct handle_object_manager_traits
  71. : pyobject_traits<typename T::element_type>
  72. {
  73. private:
  74. typedef pyobject_traits<typename T::element_type> base;
  75. public:
  76. BOOST_STATIC_CONSTANT(bool, is_specialized = true);
  77. // Initialize with a null_ok pointer for efficiency, bypassing the
  78. // null check since the source is always non-null.
  79. static null_ok<typename T::element_type>* adopt(PyObject* p)
  80. {
  81. return python::allow_null(base::checked_downcast(p));
  82. }
  83. };
  84. template <class T>
  85. struct default_object_manager_traits
  86. {
  87. BOOST_STATIC_CONSTANT(
  88. bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
  89. );
  90. };
  91. template <class T>
  92. struct object_manager_traits
  93. : mpl::if_c<
  94. is_handle<T>::value
  95. , handle_object_manager_traits<T>
  96. , default_object_manager_traits<T>
  97. >::type
  98. {
  99. };
  100. //
  101. // Traits for detecting whether a type is an object manager or a
  102. // (cv-qualified) reference to an object manager.
  103. //
  104. template <class T>
  105. struct is_object_manager
  106. : mpl::bool_<object_manager_traits<T>::is_specialized>
  107. {
  108. };
  109. # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  110. template <class T>
  111. struct is_reference_to_object_manager
  112. : mpl::false_
  113. {
  114. };
  115. template <class T>
  116. struct is_reference_to_object_manager<T&>
  117. : is_object_manager<T>
  118. {
  119. };
  120. template <class T>
  121. struct is_reference_to_object_manager<T const&>
  122. : is_object_manager<T>
  123. {
  124. };
  125. template <class T>
  126. struct is_reference_to_object_manager<T volatile&>
  127. : is_object_manager<T>
  128. {
  129. };
  130. template <class T>
  131. struct is_reference_to_object_manager<T const volatile&>
  132. : is_object_manager<T>
  133. {
  134. };
  135. # else
  136. namespace detail
  137. {
  138. typedef char (&yes_reference_to_object_manager)[1];
  139. typedef char (&no_reference_to_object_manager)[2];
  140. // A number of nastinesses go on here in order to work around MSVC6
  141. // bugs.
  142. template <class T>
  143. struct is_object_manager_help
  144. {
  145. typedef typename mpl::if_<
  146. is_object_manager<T>
  147. , yes_reference_to_object_manager
  148. , no_reference_to_object_manager
  149. >::type type;
  150. // If we just use the type instead of the result of calling this
  151. // function, VC6 will ICE.
  152. static type call();
  153. };
  154. // A set of overloads for each cv-qualification. The same argument
  155. // is passed twice: the first one is used to unwind the cv*, and the
  156. // second one is used to avoid relying on partial ordering for
  157. // overload resolution.
  158. template <class U>
  159. typename is_object_manager_help<U>
  160. is_object_manager_helper(U*, void*);
  161. template <class U>
  162. typename is_object_manager_help<U>
  163. is_object_manager_helper(U const*, void const*);
  164. template <class U>
  165. typename is_object_manager_help<U>
  166. is_object_manager_helper(U volatile*, void volatile*);
  167. template <class U>
  168. typename is_object_manager_help<U>
  169. is_object_manager_helper(U const volatile*, void const volatile*);
  170. template <class T>
  171. struct is_reference_to_object_manager_nonref
  172. : mpl::false_
  173. {
  174. };
  175. template <class T>
  176. struct is_reference_to_object_manager_ref
  177. {
  178. static T sample_object;
  179. BOOST_STATIC_CONSTANT(
  180. bool, value
  181. = (sizeof(is_object_manager_helper(&sample_object, &sample_object).call())
  182. == sizeof(detail::yes_reference_to_object_manager)
  183. )
  184. );
  185. typedef mpl::bool_<value> type;
  186. };
  187. }
  188. template <class T>
  189. struct is_reference_to_object_manager
  190. : mpl::if_<
  191. is_reference<T>
  192. , detail::is_reference_to_object_manager_ref<T>
  193. , detail::is_reference_to_object_manager_nonref<T>
  194. >::type
  195. {
  196. };
  197. # endif
  198. }}} // namespace boost::python::converter
  199. #endif // OBJECT_MANAGER_DWA2002614_HPP