data_members.hpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 DATA_MEMBERS_DWA2002328_HPP
  6. # define DATA_MEMBERS_DWA2002328_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. # include <boost/python/handle.hpp>
  9. # include <boost/python/return_value_policy.hpp>
  10. # include <boost/python/return_by_value.hpp>
  11. # include <boost/python/return_internal_reference.hpp>
  12. # include <boost/python/make_function.hpp>
  13. # include <boost/python/converter/builtin_converters.hpp>
  14. # include <boost/python/detail/indirect_traits.hpp>
  15. # include <boost/python/detail/not_specified.hpp>
  16. # include <boost/python/detail/value_arg.hpp>
  17. # include <boost/python/detail/type_traits.hpp>
  18. # include <boost/mpl/eval_if.hpp>
  19. # include <boost/mpl/if.hpp>
  20. # include <boost/mpl/vector/vector10.hpp>
  21. # include <boost/detail/workaround.hpp>
  22. namespace boost { namespace python {
  23. //
  24. // This file defines the make_getter and make_setter function
  25. // families, which are responsible for turning pointers, references,
  26. // and pointers-to-data-members into callable Python objects which
  27. // can be used for attribute access on wrapped classes.
  28. //
  29. namespace detail
  30. {
  31. // A small function object which handles the getting and setting of
  32. // data members.
  33. template <class Data, class Class>
  34. struct member
  35. {
  36. public:
  37. member(Data Class::*which) : m_which(which) {}
  38. Data& operator()(Class& c) const
  39. {
  40. return c.*m_which;
  41. }
  42. void operator()(Class& c, typename value_arg<Data>::type d) const
  43. {
  44. c.*m_which = d;
  45. }
  46. private:
  47. Data Class::*m_which;
  48. };
  49. // A small function object which handles the getting and setting of
  50. // non-member objects.
  51. template <class Data>
  52. struct datum
  53. {
  54. public:
  55. datum(Data *which) : m_which(which) {}
  56. Data& operator()() const
  57. {
  58. return *m_which;
  59. }
  60. void operator()(typename value_arg<Data>::type d) const
  61. {
  62. *m_which = d;
  63. }
  64. private:
  65. Data *m_which;
  66. };
  67. //
  68. // Helper metafunction for determining the default CallPolicy to use
  69. // for attribute access. If T is a [reference to a] class type X
  70. // whose conversion to python would normally produce a new copy of X
  71. // in a wrapped X class instance (as opposed to types such as
  72. // std::string, which are converted to native Python types, and
  73. // smart pointer types which produce a wrapped class instance of the
  74. // pointee type), to-python conversions will attempt to produce an
  75. // object which refers to the original C++ object, rather than a
  76. // copy. See default_member_getter_policy for rationale.
  77. //
  78. template <class T>
  79. struct default_getter_by_ref
  80. : mpl::and_<
  81. mpl::bool_<
  82. to_python_value<
  83. typename value_arg<T>::type
  84. >::uses_registry
  85. >
  86. , indirect_traits::is_reference_to_class<
  87. typename value_arg<T>::type
  88. >
  89. >
  90. {
  91. };
  92. // Metafunction computing the default CallPolicy to use for reading
  93. // data members
  94. //
  95. // If it's a regular class type (not an object manager or other
  96. // type for which we have to_python specializations, use
  97. // return_internal_reference so that we can do things like
  98. // x.y.z = 1
  99. // and get the right result.
  100. template <class T>
  101. struct default_member_getter_policy
  102. : mpl::if_<
  103. default_getter_by_ref<T>
  104. , return_internal_reference<>
  105. , return_value_policy<return_by_value>
  106. >
  107. {};
  108. // Metafunction computing the default CallPolicy to use for reading
  109. // non-member data.
  110. template <class T>
  111. struct default_datum_getter_policy
  112. : mpl::if_<
  113. default_getter_by_ref<T>
  114. , return_value_policy<reference_existing_object>
  115. , return_value_policy<return_by_value>
  116. >
  117. {};
  118. //
  119. // make_getter helper function family -- These helpers to
  120. // boost::python::make_getter are used to dispatch behavior. The
  121. // third argument is a workaround for a CWPro8 partial ordering bug
  122. // with pointers to data members. It should be convertible to
  123. // detail::true_ iff the first argument is a pointer-to-member, and
  124. // detail::false_ otherwise. The fourth argument is for compilers
  125. // which don't support partial ordering at all and should always be
  126. // passed 0L.
  127. #if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
  128. template <class D, class P>
  129. inline object make_getter(D& d, P& p, detail::false_, ...);
  130. #endif
  131. // Handle non-member pointers with policies
  132. template <class D, class Policies>
  133. inline object make_getter(D* d, Policies const& policies, detail::false_, int)
  134. {
  135. return python::make_function(
  136. detail::datum<D>(d), policies, mpl::vector1<D&>()
  137. );
  138. }
  139. // Handle non-member pointers without policies
  140. template <class D>
  141. inline object make_getter(D* d, not_specified, detail::false_, long)
  142. {
  143. typedef typename default_datum_getter_policy<D>::type policies;
  144. return detail::make_getter(d, policies(), detail::false_(), 0);
  145. }
  146. // Handle pointers-to-members with policies
  147. template <class C, class D, class Policies>
  148. inline object make_getter(D C::*pm, Policies const& policies, detail::true_, int)
  149. {
  150. #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
  151. typedef typename detail::remove_cv<C>::type Class;
  152. #else
  153. typedef C Class;
  154. #endif
  155. return python::make_function(
  156. detail::member<D,Class>(pm)
  157. , policies
  158. , mpl::vector2<D&,Class&>()
  159. );
  160. }
  161. // Handle pointers-to-members without policies
  162. template <class C, class D>
  163. inline object make_getter(D C::*pm, not_specified, detail::true_, long)
  164. {
  165. typedef typename default_member_getter_policy<D>::type policies;
  166. return detail::make_getter(pm, policies(), detail::true_(), 0);
  167. }
  168. // Handle references
  169. template <class D, class P>
  170. inline object make_getter(D& d, P& p, detail::false_, ...)
  171. {
  172. // Just dispatch to the handler for pointer types.
  173. return detail::make_getter(&d, p, detail::false_(), 0L);
  174. }
  175. //
  176. // make_setter helper function family -- These helpers to
  177. // boost::python::make_setter are used to dispatch behavior. The
  178. // third argument is for compilers which don't support partial
  179. // ordering at all and should always be passed 0.
  180. //
  181. // Handle non-member pointers
  182. template <class D, class Policies>
  183. inline object make_setter(D* p, Policies const& policies, detail::false_, int)
  184. {
  185. return python::make_function(
  186. detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
  187. );
  188. }
  189. // Handle pointers-to-members
  190. template <class C, class D, class Policies>
  191. inline object make_setter(D C::*pm, Policies const& policies, detail::true_, int)
  192. {
  193. return python::make_function(
  194. detail::member<D,C>(pm)
  195. , policies
  196. , mpl::vector3<void, C&, D const&>()
  197. );
  198. }
  199. // Handle references
  200. template <class D, class Policies>
  201. inline object make_setter(D& x, Policies const& policies, detail::false_, ...)
  202. {
  203. return detail::make_setter(&x, policies, detail::false_(), 0L);
  204. }
  205. }
  206. //
  207. // make_getter function family -- build a callable object which
  208. // retrieves data through the first argument and is appropriate for
  209. // use as the `get' function in Python properties . The second,
  210. // policies argument, is optional. We need both D& and D const&
  211. // overloads in order be able to handle rvalues.
  212. //
  213. template <class D, class Policies>
  214. inline object make_getter(D& d, Policies const& policies)
  215. {
  216. return detail::make_getter(d, policies, detail::is_member_pointer<D>(), 0L);
  217. }
  218. template <class D, class Policies>
  219. inline object make_getter(D const& d, Policies const& policies)
  220. {
  221. return detail::make_getter(d, policies, detail::is_member_pointer<D>(), 0L);
  222. }
  223. template <class D>
  224. inline object make_getter(D& x)
  225. {
  226. detail::not_specified policy
  227. = detail::not_specified(); // suppress a SunPro warning
  228. return detail::make_getter(x, policy, detail::is_member_pointer<D>(), 0L);
  229. }
  230. # if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
  231. template <class D>
  232. inline object make_getter(D const& d)
  233. {
  234. detail::not_specified policy
  235. = detail::not_specified(); // Suppress a SunPro warning
  236. return detail::make_getter(d, policy, detail::is_member_pointer<D>(), 0L);
  237. }
  238. # endif
  239. //
  240. // make_setter function family -- build a callable object which
  241. // writes data through the first argument and is appropriate for
  242. // use as the `set' function in Python properties . The second,
  243. // policies argument, is optional. We need both D& and D const&
  244. // overloads in order be able to handle rvalues.
  245. //
  246. template <class D, class Policies>
  247. inline object make_setter(D& x, Policies const& policies)
  248. {
  249. return detail::make_setter(x, policies, detail::is_member_pointer<D>(), 0);
  250. }
  251. template <class D, class Policies>
  252. inline object make_setter(D const& x, Policies const& policies)
  253. {
  254. return detail::make_setter(x, policies, detail::is_member_pointer<D>(), 0);
  255. }
  256. template <class D>
  257. inline object make_setter(D& x)
  258. {
  259. return detail::make_setter(x, default_call_policies(), detail::is_member_pointer<D>(), 0);
  260. }
  261. # if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
  262. template <class D>
  263. inline object make_setter(D const& x)
  264. {
  265. return detail::make_setter(x, default_call_policies(), detail::is_member_pointer<D>(), 0);
  266. }
  267. # endif
  268. }} // namespace boost::python
  269. #endif // DATA_MEMBERS_DWA2002328_HPP