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, mpl::true_) const
  38. {
  39. std::auto_ptr<U> owner(x);
  40. dispatch(owner, mpl::false_());
  41. }
  42. template <class Ptr>
  43. void dispatch(Ptr x, mpl::false_) const
  44. {
  45. typedef typename pointee<Ptr>::type value_type;
  46. typedef objects::pointer_holder<Ptr,value_type> holder;
  47. typedef objects::instance<holder> instance_t;
  48. void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
  49. try {
  50. (new (memory) holder(x))->install(this->m_self);
  51. }
  52. catch(...) {
  53. holder::deallocate(this->m_self, memory);
  54. throw;
  55. }
  56. }
  57. PyObject* m_self;
  58. };
  59. struct constructor_result_converter
  60. {
  61. template <class T>
  62. struct apply
  63. {
  64. typedef install_holder<T> type;
  65. };
  66. };
  67. template <class BaseArgs, class Offset>
  68. struct offset_args
  69. {
  70. offset_args(BaseArgs base_) : base(base_) {}
  71. BaseArgs base;
  72. };
  73. template <int N, class BaseArgs, class Offset>
  74. inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
  75. {
  76. return get(mpl::int_<(N+Offset::value)>(), args_.base);
  77. }
  78. template <class BaseArgs, class Offset>
  79. inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
  80. {
  81. return arity(args_.base) - Offset::value;
  82. }
  83. template <class BasePolicy_ = default_call_policies>
  84. struct constructor_policy : BasePolicy_
  85. {
  86. constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
  87. // If the BasePolicy_ supplied a result converter it would be
  88. // ignored; issue an error if it's not the default.
  89. #if defined _MSC_VER && _MSC_VER < 1300
  90. typedef is_same<
  91. typename BasePolicy_::result_converter
  92. , default_result_converter
  93. > same_result_converter;
  94. //see above for explanation
  95. BOOST_STATIC_ASSERT(same_result_converter::value) ;
  96. #else
  97. BOOST_MPL_ASSERT_MSG(
  98. (is_same<
  99. typename BasePolicy_::result_converter
  100. , default_result_converter
  101. >::value)
  102. , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
  103. , (typename BasePolicy_::result_converter)
  104. );
  105. #endif
  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;
  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