9
3

init.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright David Abrahams 2002, Joel de Guzman, 2002.
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #ifndef INIT_JDG20020820_HPP
  10. #define INIT_JDG20020820_HPP
  11. # include <boost/python/detail/prefix.hpp>
  12. #include <boost/python/detail/type_list.hpp>
  13. #include <boost/python/args_fwd.hpp>
  14. #include <boost/python/detail/make_keyword_range_fn.hpp>
  15. #include <boost/python/def_visitor.hpp>
  16. #include <boost/mpl/if.hpp>
  17. #include <boost/mpl/eval_if.hpp>
  18. #include <boost/mpl/size.hpp>
  19. #include <boost/mpl/iterator_range.hpp>
  20. #include <boost/mpl/empty.hpp>
  21. #include <boost/mpl/begin_end.hpp>
  22. #include <boost/mpl/bool.hpp>
  23. #include <boost/mpl/prior.hpp>
  24. #include <boost/mpl/joint_view.hpp>
  25. #include <boost/mpl/back.hpp>
  26. #include <boost/python/detail/type_traits.hpp>
  27. #include <boost/preprocessor/enum_params_with_a_default.hpp>
  28. #include <boost/preprocessor/enum_params.hpp>
  29. #include <utility>
  30. ///////////////////////////////////////////////////////////////////////////////
  31. #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \
  32. BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \
  33. BOOST_PYTHON_MAX_ARITY, \
  34. class T, \
  35. mpl::void_) \
  36. #define BOOST_PYTHON_OVERLOAD_TYPES \
  37. BOOST_PP_ENUM_PARAMS_Z(1, \
  38. BOOST_PYTHON_MAX_ARITY, \
  39. class T) \
  40. #define BOOST_PYTHON_OVERLOAD_ARGS \
  41. BOOST_PP_ENUM_PARAMS_Z(1, \
  42. BOOST_PYTHON_MAX_ARITY, \
  43. T) \
  44. ///////////////////////////////////////////////////////////////////////////////
  45. namespace boost { namespace python {
  46. template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
  47. class init; // forward declaration
  48. template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
  49. struct optional; // forward declaration
  50. namespace detail
  51. {
  52. namespace error
  53. {
  54. template <int keywords, int init_args>
  55. struct more_keywords_than_init_arguments
  56. {
  57. typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1] BOOST_ATTRIBUTE_UNUSED;
  58. };
  59. }
  60. // is_optional<T>::value
  61. //
  62. // This metaprogram checks if T is an optional
  63. //
  64. template <class T>
  65. struct is_optional
  66. : mpl::false_
  67. {};
  68. template <BOOST_PYTHON_OVERLOAD_TYPES>
  69. struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> >
  70. : mpl::true_
  71. {};
  72. template <int NDefaults>
  73. struct define_class_init_helper;
  74. } // namespace detail
  75. template <class DerivedT>
  76. struct init_base : def_visitor<DerivedT>
  77. {
  78. init_base(char const* doc_, detail::keyword_range const& keywords_)
  79. : m_doc(doc_), m_keywords(keywords_)
  80. {}
  81. init_base(char const* doc_)
  82. : m_doc(doc_)
  83. {}
  84. DerivedT const& derived() const
  85. {
  86. return *static_cast<DerivedT const*>(this);
  87. }
  88. char const* doc_string() const
  89. {
  90. return m_doc;
  91. }
  92. detail::keyword_range const& keywords() const
  93. {
  94. return m_keywords;
  95. }
  96. static default_call_policies call_policies()
  97. {
  98. return default_call_policies();
  99. }
  100. private:
  101. // visit
  102. //
  103. // Defines a set of n_defaults + 1 constructors for its
  104. // class_<...> argument. Each constructor after the first has
  105. // one less argument to its right. Example:
  106. //
  107. // init<int, optional<char, long, double> >
  108. //
  109. // Defines:
  110. //
  111. // __init__(int, char, long, double)
  112. // __init__(int, char, long)
  113. // __init__(int, char)
  114. // __init__(int)
  115. template <class classT>
  116. void visit(classT& cl) const
  117. {
  118. typedef typename DerivedT::signature signature;
  119. typedef typename DerivedT::n_arguments n_arguments;
  120. typedef typename DerivedT::n_defaults n_defaults;
  121. detail::define_class_init_helper<n_defaults::value>::apply(
  122. cl
  123. , derived().call_policies()
  124. , signature()
  125. , n_arguments()
  126. , derived().doc_string()
  127. , derived().keywords());
  128. }
  129. friend class python::def_visitor_access;
  130. private: // data members
  131. char const* m_doc;
  132. detail::keyword_range m_keywords;
  133. };
  134. template <class CallPoliciesT, class InitT>
  135. class init_with_call_policies
  136. : public init_base<init_with_call_policies<CallPoliciesT, InitT> >
  137. {
  138. typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base;
  139. public:
  140. typedef typename InitT::n_arguments n_arguments;
  141. typedef typename InitT::n_defaults n_defaults;
  142. typedef typename InitT::signature signature;
  143. init_with_call_policies(
  144. CallPoliciesT const& policies_
  145. , char const* doc_
  146. , detail::keyword_range const& keywords
  147. )
  148. : base(doc_, keywords)
  149. , m_policies(policies_)
  150. {}
  151. CallPoliciesT const& call_policies() const
  152. {
  153. return this->m_policies;
  154. }
  155. private: // data members
  156. CallPoliciesT m_policies;
  157. };
  158. //
  159. // drop1<S> is the initial length(S) elements of S
  160. //
  161. namespace detail
  162. {
  163. template <class S>
  164. struct drop1
  165. : mpl::iterator_range<
  166. typename mpl::begin<S>::type
  167. , typename mpl::prior<
  168. typename mpl::end<S>::type
  169. >::type
  170. >
  171. {};
  172. }
  173. template <BOOST_PYTHON_OVERLOAD_TYPES>
  174. class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
  175. {
  176. typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base;
  177. public:
  178. typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t;
  179. init(char const* doc_ = 0)
  180. : base(doc_)
  181. {
  182. }
  183. template <std::size_t N>
  184. init(char const* doc_, detail::keywords<N> const& kw)
  185. : base(doc_, kw.range())
  186. {
  187. typedef typename detail::error::more_keywords_than_init_arguments<
  188. N, n_arguments::value + 1
  189. >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
  190. }
  191. template <std::size_t N>
  192. init(detail::keywords<N> const& kw, char const* doc_ = 0)
  193. : base(doc_, kw.range())
  194. {
  195. typedef typename detail::error::more_keywords_than_init_arguments<
  196. N, n_arguments::value + 1
  197. >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
  198. }
  199. template <class CallPoliciesT>
  200. init_with_call_policies<CallPoliciesT, self_t>
  201. operator[](CallPoliciesT const& policies) const
  202. {
  203. return init_with_call_policies<CallPoliciesT, self_t>(
  204. policies, this->doc_string(), this->keywords());
  205. }
  206. typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_;
  207. typedef detail::is_optional<
  208. typename mpl::eval_if<
  209. mpl::empty<signature_>
  210. , mpl::false_
  211. , mpl::back<signature_>
  212. >::type
  213. > back_is_optional;
  214. typedef typename mpl::eval_if<
  215. back_is_optional
  216. , mpl::back<signature_>
  217. , mpl::vector0<>
  218. >::type optional_args;
  219. typedef typename mpl::eval_if<
  220. back_is_optional
  221. , mpl::if_<
  222. mpl::empty<optional_args>
  223. , detail::drop1<signature_>
  224. , mpl::joint_view<
  225. detail::drop1<signature_>
  226. , optional_args
  227. >
  228. >
  229. , signature_
  230. >::type signature;
  231. // TODO: static assert to make sure there are no other optional elements
  232. // Count the number of default args
  233. typedef mpl::size<optional_args> n_defaults;
  234. typedef mpl::size<signature> n_arguments;
  235. };
  236. ///////////////////////////////////////////////////////////////////////////////
  237. //
  238. // optional
  239. //
  240. // optional<T0...TN>::type returns a typelist.
  241. //
  242. ///////////////////////////////////////////////////////////////////////////////
  243. template <BOOST_PYTHON_OVERLOAD_TYPES>
  244. struct optional
  245. : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS>
  246. {
  247. };
  248. namespace detail
  249. {
  250. template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
  251. inline void def_init_aux(
  252. ClassT& cl
  253. , Signature const&
  254. , NArgs
  255. , CallPoliciesT const& policies
  256. , char const* doc
  257. , detail::keyword_range const& keywords_
  258. )
  259. {
  260. cl.def(
  261. "__init__"
  262. , detail::make_keyword_range_constructor<Signature,NArgs>(
  263. policies
  264. , keywords_
  265. , (typename ClassT::metadata::holder*)0
  266. )
  267. , doc
  268. );
  269. }
  270. ///////////////////////////////////////////////////////////////////////////////
  271. //
  272. // define_class_init_helper<N>::apply
  273. //
  274. // General case
  275. //
  276. // Accepts a class_ and an arguments list. Defines a constructor
  277. // for the class given the arguments and recursively calls
  278. // define_class_init_helper<N-1>::apply with one fewer argument (the
  279. // rightmost argument is shaved off)
  280. //
  281. ///////////////////////////////////////////////////////////////////////////////
  282. template <int NDefaults>
  283. struct define_class_init_helper
  284. {
  285. template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
  286. static void apply(
  287. ClassT& cl
  288. , CallPoliciesT const& policies
  289. , Signature const& args
  290. , NArgs
  291. , char const* doc
  292. , detail::keyword_range keywords)
  293. {
  294. detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
  295. if (keywords.second > keywords.first)
  296. --keywords.second;
  297. typedef typename mpl::prior<NArgs>::type next_nargs;
  298. define_class_init_helper<NDefaults-1>::apply(
  299. cl, policies, Signature(), next_nargs(), doc, keywords);
  300. }
  301. };
  302. ///////////////////////////////////////////////////////////////////////////////
  303. //
  304. // define_class_init_helper<0>::apply
  305. //
  306. // Terminal case
  307. //
  308. // Accepts a class_ and an arguments list. Defines a constructor
  309. // for the class given the arguments.
  310. //
  311. ///////////////////////////////////////////////////////////////////////////////
  312. template <>
  313. struct define_class_init_helper<0> {
  314. template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
  315. static void apply(
  316. ClassT& cl
  317. , CallPoliciesT const& policies
  318. , Signature const& args
  319. , NArgs
  320. , char const* doc
  321. , detail::keyword_range const& keywords)
  322. {
  323. detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
  324. }
  325. };
  326. }
  327. }} // namespace boost::python
  328. #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
  329. #undef BOOST_PYTHON_OVERLOAD_TYPES
  330. #undef BOOST_PYTHON_OVERLOAD_ARGS
  331. #undef BOOST_PYTHON_IS_OPTIONAL_VALUE
  332. #undef BOOST_PYTHON_APPEND_TO_INIT
  333. ///////////////////////////////////////////////////////////////////////////////
  334. #endif // INIT_JDG20020820_HPP