make_constructor.hpp 8.4 KB

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