make_constructor.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright David Abrahams 2001.
  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 MAKE_CONSTRUCTOR_DWA20011221_HPP
  6. # define MAKE_CONSTRUCTOR_DWA20011221_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. # include <boost/python/default_call_policies.hpp>
  9. # include <boost/python/args.hpp>
  10. # include <boost/python/object_fwd.hpp>
  11. # include <boost/python/object/function_object.hpp>
  12. # include <boost/python/object/make_holder.hpp>
  13. # include <boost/python/object/pointer_holder.hpp>
  14. # include <boost/python/converter/context_result_converter.hpp>
  15. # include <boost/python/detail/caller.hpp>
  16. # include <boost/python/detail/none.hpp>
  17. # include <boost/mpl/size.hpp>
  18. # include <boost/mpl/int.hpp>
  19. # include <boost/mpl/push_front.hpp>
  20. # include <boost/mpl/pop_front.hpp>
  21. # include <boost/mpl/assert.hpp>
  22. namespace boost { namespace python {
  23. namespace detail
  24. {
  25. template <class T>
  26. struct install_holder : converter::context_result_converter
  27. {
  28. install_holder(PyObject* args_)
  29. : m_self(PyTuple_GetItem(args_, 0)) {}
  30. PyObject* operator()(T x) const
  31. {
  32. dispatch(x, is_pointer<T>());
  33. return none();
  34. }
  35. private:
  36. template <class U>
  37. void dispatch(U* x, detail::true_) const
  38. {
  39. #if defined(BOOST_NO_CXX11_SMART_PTR)
  40. std::auto_ptr<U> owner(x);
  41. dispatch(owner, detail::false_());
  42. #else
  43. std::unique_ptr<U> owner(x);
  44. dispatch(std::move(owner), detail::false_());
  45. #endif
  46. }
  47. template <class Ptr>
  48. void dispatch(Ptr x, detail::false_) const
  49. {
  50. typedef typename pointee<Ptr>::type value_type;
  51. typedef objects::pointer_holder<Ptr,value_type> holder;
  52. typedef objects::instance<holder> instance_t;
  53. void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder),
  54. boost::python::detail::alignment_of<holder>::value);
  55. try {
  56. #if defined(BOOST_NO_CXX11_SMART_PTR)
  57. (new (memory) holder(x))->install(this->m_self);
  58. #else
  59. (new (memory) holder(std::move(x)))->install(this->m_self);
  60. #endif
  61. }
  62. catch(...) {
  63. holder::deallocate(this->m_self, memory);
  64. throw;
  65. }
  66. }
  67. PyObject* m_self;
  68. };
  69. struct constructor_result_converter
  70. {
  71. template <class T>
  72. struct apply
  73. {
  74. typedef install_holder<T> type;
  75. };
  76. };
  77. template <class BaseArgs, class Offset>
  78. struct offset_args
  79. {
  80. offset_args(BaseArgs base_) : base(base_) {}
  81. BaseArgs base;
  82. };
  83. template <int N, class BaseArgs, class Offset>
  84. inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
  85. {
  86. return get(mpl::int_<(N+Offset::value)>(), args_.base);
  87. }
  88. template <class BaseArgs, class Offset>
  89. inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
  90. {
  91. return arity(args_.base) - Offset::value;
  92. }
  93. template <class BasePolicy_ = default_call_policies>
  94. struct constructor_policy : BasePolicy_
  95. {
  96. constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
  97. // If the BasePolicy_ supplied a result converter it would be
  98. // ignored; issue an error if it's not the default.
  99. BOOST_MPL_ASSERT_MSG(
  100. (is_same<
  101. typename BasePolicy_::result_converter
  102. , default_result_converter
  103. >::value)
  104. , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
  105. , (typename BasePolicy_::result_converter)
  106. );
  107. typedef constructor_result_converter result_converter;
  108. typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
  109. };
  110. template <class InnerSignature>
  111. struct outer_constructor_signature
  112. {
  113. typedef typename mpl::pop_front<InnerSignature>::type inner_args;
  114. typedef typename mpl::push_front<inner_args,object>::type outer_args;
  115. typedef typename mpl::push_front<outer_args,void>::type type;
  116. };
  117. // ETI workaround
  118. template <>
  119. struct outer_constructor_signature<int>
  120. {
  121. typedef int type;
  122. };
  123. //
  124. // These helper functions for make_constructor (below) do the raw work
  125. // of constructing a Python object from some invokable entity. See
  126. // <boost/python/detail/caller.hpp> for more information about how
  127. // the Sig arguments is used.
  128. //
  129. // @group make_constructor_aux {
  130. template <class F, class CallPolicies, class Sig>
  131. object make_constructor_aux(
  132. F f // An object that can be invoked by detail::invoke()
  133. , CallPolicies const& p // CallPolicies to use in the invocation
  134. , Sig const& // An MPL sequence of argument types expected by F
  135. )
  136. {
  137. typedef typename outer_constructor_signature<Sig>::type outer_signature;
  138. typedef constructor_policy<CallPolicies> inner_policy;
  139. return objects::function_object(
  140. objects::py_function(
  141. detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
  142. , outer_signature()
  143. )
  144. );
  145. }
  146. // As above, except that it accepts argument keywords. NumKeywords
  147. // is used only for a compile-time assertion to make sure the user
  148. // doesn't pass more keywords than the function can accept. To
  149. // disable all checking, pass mpl::int_<0> for NumKeywords.
  150. template <class F, class CallPolicies, class Sig, class NumKeywords>
  151. object make_constructor_aux(
  152. F f
  153. , CallPolicies const& p
  154. , Sig const&
  155. , detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
  156. , NumKeywords // An MPL integral type wrapper: the size of kw
  157. )
  158. {
  159. enum { arity = mpl::size<Sig>::value - 1 };
  160. typedef typename detail::error::more_keywords_than_function_arguments<
  161. NumKeywords::value, arity
  162. >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
  163. typedef typename outer_constructor_signature<Sig>::type outer_signature;
  164. typedef constructor_policy<CallPolicies> inner_policy;
  165. return objects::function_object(
  166. objects::py_function(
  167. detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
  168. , outer_signature()
  169. )
  170. , kw
  171. );
  172. }
  173. // }
  174. //
  175. // These dispatch functions are used to discriminate between the
  176. // cases when the 3rd argument is keywords or when it is a
  177. // signature.
  178. //
  179. // @group Helpers for make_constructor when called with 3 arguments. {
  180. //
  181. template <class F, class CallPolicies, class Keywords>
  182. object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
  183. {
  184. return detail::make_constructor_aux(
  185. f
  186. , policies
  187. , detail::get_signature(f)
  188. , kw.range()
  189. , mpl::int_<Keywords::size>()
  190. );
  191. }
  192. template <class F, class CallPolicies, class Signature>
  193. object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
  194. {
  195. return detail::make_constructor_aux(
  196. f
  197. , policies
  198. , sig
  199. );
  200. }
  201. // }
  202. }
  203. // These overloaded functions wrap a function or member function
  204. // pointer as a Python object, using optional CallPolicies,
  205. // Keywords, and/or Signature. @group {
  206. //
  207. template <class F>
  208. object make_constructor(F f)
  209. {
  210. return detail::make_constructor_aux(
  211. f,default_call_policies(), detail::get_signature(f));
  212. }
  213. template <class F, class CallPolicies>
  214. object make_constructor(F f, CallPolicies const& policies)
  215. {
  216. return detail::make_constructor_aux(
  217. f, policies, detail::get_signature(f));
  218. }
  219. template <class F, class CallPolicies, class KeywordsOrSignature>
  220. object make_constructor(
  221. F f
  222. , CallPolicies const& policies
  223. , KeywordsOrSignature const& keywords_or_signature)
  224. {
  225. typedef typename
  226. detail::is_reference_to_keywords<KeywordsOrSignature&>::type
  227. is_kw;
  228. return detail::make_constructor_dispatch(
  229. f
  230. , policies
  231. , keywords_or_signature
  232. , is_kw()
  233. );
  234. }
  235. template <class F, class CallPolicies, class Keywords, class Signature>
  236. object make_constructor(
  237. F f
  238. , CallPolicies const& policies
  239. , Keywords const& kw
  240. , Signature const& sig
  241. )
  242. {
  243. return detail::make_constructor_aux(
  244. f
  245. , policies
  246. , sig
  247. , kw.range()
  248. , mpl::int_<Keywords::size>()
  249. );
  250. }
  251. // }
  252. }}
  253. #endif // MAKE_CONSTRUCTOR_DWA20011221_HPP