1 ///////////////////////////////////////////////////////////////////////////////
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)
8 ///////////////////////////////////////////////////////////////////////////////
9 #ifndef INIT_JDG20020820_HPP
10 #define INIT_JDG20020820_HPP
12 # include <boost/python/detail/prefix.hpp>
14 #include <boost/python/detail/type_list.hpp>
15 #include <boost/python/args_fwd.hpp>
16 #include <boost/python/detail/make_keyword_range_fn.hpp>
17 #include <boost/python/def_visitor.hpp>
19 #include <boost/mpl/if.hpp>
20 #include <boost/mpl/eval_if.hpp>
21 #include <boost/mpl/size.hpp>
22 #include <boost/mpl/iterator_range.hpp>
23 #include <boost/mpl/empty.hpp>
24 #include <boost/mpl/begin_end.hpp>
25 #include <boost/mpl/bool.hpp>
26 #include <boost/mpl/prior.hpp>
27 #include <boost/mpl/joint_view.hpp>
28 #include <boost/mpl/back.hpp>
30 #include <boost/python/detail/type_traits.hpp>
32 #include <boost/preprocessor/enum_params_with_a_default.hpp>
33 #include <boost/preprocessor/enum_params.hpp>
37 ///////////////////////////////////////////////////////////////////////////////
38 #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \
39 BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \
40 BOOST_PYTHON_MAX_ARITY, \
44 #define BOOST_PYTHON_OVERLOAD_TYPES \
45 BOOST_PP_ENUM_PARAMS_Z(1, \
46 BOOST_PYTHON_MAX_ARITY, \
49 #define BOOST_PYTHON_OVERLOAD_ARGS \
50 BOOST_PP_ENUM_PARAMS_Z(1, \
51 BOOST_PYTHON_MAX_ARITY, \
54 ///////////////////////////////////////////////////////////////////////////////
55 namespace boost { namespace python {
57 template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
58 class init; // forward declaration
61 template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
62 struct optional; // forward declaration
68 template <int keywords, int init_args>
69 struct more_keywords_than_init_arguments
71 typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1] BOOST_ATTRIBUTE_UNUSED;
75 // is_optional<T>::value
77 // This metaprogram checks if T is an optional
85 template <BOOST_PYTHON_OVERLOAD_TYPES>
86 struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> >
91 template <int NDefaults>
92 struct define_class_init_helper;
96 template <class DerivedT>
97 struct init_base : def_visitor<DerivedT>
99 init_base(char const* doc_, detail::keyword_range const& keywords_)
100 : m_doc(doc_), m_keywords(keywords_)
103 init_base(char const* doc_)
107 DerivedT const& derived() const
109 return *static_cast<DerivedT const*>(this);
112 char const* doc_string() const
117 detail::keyword_range const& keywords() const
122 static default_call_policies call_policies()
124 return default_call_policies();
130 // Defines a set of n_defaults + 1 constructors for its
131 // class_<...> argument. Each constructor after the first has
132 // one less argument to its right. Example:
134 // init<int, optional<char, long, double> >
138 // __init__(int, char, long, double)
139 // __init__(int, char, long)
140 // __init__(int, char)
142 template <class classT>
143 void visit(classT& cl) const
145 typedef typename DerivedT::signature signature;
146 typedef typename DerivedT::n_arguments n_arguments;
147 typedef typename DerivedT::n_defaults n_defaults;
149 detail::define_class_init_helper<n_defaults::value>::apply(
151 , derived().call_policies()
154 , derived().doc_string()
155 , derived().keywords());
158 friend class python::def_visitor_access;
160 private: // data members
162 detail::keyword_range m_keywords;
165 template <class CallPoliciesT, class InitT>
166 class init_with_call_policies
167 : public init_base<init_with_call_policies<CallPoliciesT, InitT> >
169 typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base;
171 typedef typename InitT::n_arguments n_arguments;
172 typedef typename InitT::n_defaults n_defaults;
173 typedef typename InitT::signature signature;
175 init_with_call_policies(
176 CallPoliciesT const& policies_
178 , detail::keyword_range const& keywords
180 : base(doc_, keywords)
181 , m_policies(policies_)
184 CallPoliciesT const& call_policies() const
186 return this->m_policies;
189 private: // data members
190 CallPoliciesT m_policies;
194 // drop1<S> is the initial length(S) elements of S
200 : mpl::iterator_range<
201 typename mpl::begin<S>::type
202 , typename mpl::prior<
203 typename mpl::end<S>::type
209 template <BOOST_PYTHON_OVERLOAD_TYPES>
210 class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
212 typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base;
214 typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t;
216 init(char const* doc_ = 0)
221 template <std::size_t N>
222 init(char const* doc_, detail::keywords<N> const& kw)
223 : base(doc_, kw.range())
225 typedef typename detail::error::more_keywords_than_init_arguments<
226 N, n_arguments::value + 1
227 >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
230 template <std::size_t N>
231 init(detail::keywords<N> const& kw, char const* doc_ = 0)
232 : base(doc_, kw.range())
234 typedef typename detail::error::more_keywords_than_init_arguments<
235 N, n_arguments::value + 1
236 >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
239 template <class CallPoliciesT>
240 init_with_call_policies<CallPoliciesT, self_t>
241 operator[](CallPoliciesT const& policies) const
243 return init_with_call_policies<CallPoliciesT, self_t>(
244 policies, this->doc_string(), this->keywords());
247 typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_;
249 typedef detail::is_optional<
250 typename mpl::eval_if<
251 mpl::empty<signature_>
253 , mpl::back<signature_>
257 typedef typename mpl::eval_if<
259 , mpl::back<signature_>
261 >::type optional_args;
263 typedef typename mpl::eval_if<
266 mpl::empty<optional_args>
267 , detail::drop1<signature_>
269 detail::drop1<signature_>
276 // TODO: static assert to make sure there are no other optional elements
278 // Count the number of default args
279 typedef mpl::size<optional_args> n_defaults;
280 typedef mpl::size<signature> n_arguments;
283 ///////////////////////////////////////////////////////////////////////////////
287 // optional<T0...TN>::type returns a typelist.
289 ///////////////////////////////////////////////////////////////////////////////
290 template <BOOST_PYTHON_OVERLOAD_TYPES>
292 : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS>
298 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
299 inline void def_init_aux(
303 , CallPoliciesT const& policies
305 , detail::keyword_range const& keywords_
310 , detail::make_keyword_range_constructor<Signature,NArgs>(
313 , (typename ClassT::metadata::holder*)0
319 ///////////////////////////////////////////////////////////////////////////////
321 // define_class_init_helper<N>::apply
325 // Accepts a class_ and an arguments list. Defines a constructor
326 // for the class given the arguments and recursively calls
327 // define_class_init_helper<N-1>::apply with one fewer argument (the
328 // rightmost argument is shaved off)
330 ///////////////////////////////////////////////////////////////////////////////
331 template <int NDefaults>
332 struct define_class_init_helper
335 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
338 , CallPoliciesT const& policies
339 , Signature const& args
342 , detail::keyword_range keywords)
344 detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
346 if (keywords.second > keywords.first)
349 typedef typename mpl::prior<NArgs>::type next_nargs;
350 define_class_init_helper<NDefaults-1>::apply(
351 cl, policies, Signature(), next_nargs(), doc, keywords);
355 ///////////////////////////////////////////////////////////////////////////////
357 // define_class_init_helper<0>::apply
361 // Accepts a class_ and an arguments list. Defines a constructor
362 // for the class given the arguments.
364 ///////////////////////////////////////////////////////////////////////////////
366 struct define_class_init_helper<0> {
368 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
371 , CallPoliciesT const& policies
372 , Signature const& args
375 , detail::keyword_range const& keywords)
377 detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
382 }} // namespace boost::python
384 #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
385 #undef BOOST_PYTHON_OVERLOAD_TYPES
386 #undef BOOST_PYTHON_OVERLOAD_ARGS
387 #undef BOOST_PYTHON_IS_OPTIONAL_VALUE
388 #undef BOOST_PYTHON_APPEND_TO_INIT
390 ///////////////////////////////////////////////////////////////////////////////
391 #endif // INIT_JDG20020820_HPP