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
12# include <boost/python/detail/prefix.hpp>
13
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>
18
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>
29
30#include <boost/type_traits/is_same.hpp>
31
32#include <boost/preprocessor/enum_params_with_a_default.hpp>
33#include <boost/preprocessor/enum_params.hpp>
34
35#include <utility>
36
37///////////////////////////////////////////////////////////////////////////////
38#define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \
39 BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \
40 BOOST_PYTHON_MAX_ARITY, \
41 class T, \
42 mpl::void_) \
43
44#define BOOST_PYTHON_OVERLOAD_TYPES \
45 BOOST_PP_ENUM_PARAMS_Z(1, \
46 BOOST_PYTHON_MAX_ARITY, \
47 class T) \
48
49#define BOOST_PYTHON_OVERLOAD_ARGS \
50 BOOST_PP_ENUM_PARAMS_Z(1, \
51 BOOST_PYTHON_MAX_ARITY, \
52 T) \
53
54///////////////////////////////////////////////////////////////////////////////
55namespace boost { namespace python {
56
57template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
58class init; // forward declaration
59
60
61template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
62struct optional; // forward declaration
63
64namespace detail
65{
66 namespace error
67 {
68 template <int keywords, int init_args>
69 struct more_keywords_than_init_arguments
70 {
71 typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1];
72 };
73 }
74
75 // is_optional<T>::value
76 //
77 // This metaprogram checks if T is an optional
78 //
79
80 template <class T>
81 struct is_optional
82 : mpl::false_
83 {};
84
85 template <BOOST_PYTHON_OVERLOAD_TYPES>
86 struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> >
87 : mpl::true_
88 {};
89
90
91 template <int NDefaults>
92 struct define_class_init_helper;
93
94} // namespace detail
95
96template <class DerivedT>
97struct init_base : def_visitor<DerivedT>
98{
99 init_base(char const* doc_, detail::keyword_range const& keywords_)
100 : m_doc(doc_), m_keywords(keywords_)
101 {}
102
103 init_base(char const* doc_)
104 : m_doc(doc_)
105 {}
106
107 DerivedT const& derived() const
108 {
109 return *static_cast<DerivedT const*>(this);
110 }
111
112 char const* doc_string() const
113 {
114 return m_doc;
115 }
116
117 detail::keyword_range const& keywords() const
118 {
119 return m_keywords;
120 }
121
122 static default_call_policies call_policies()
123 {
124 return default_call_policies();
125 }
126
127 private:
128 // visit
129 //
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:
133 //
134 // init<int, optional<char, long, double> >
135 //
136 // Defines:
137 //
138 // __init__(int, char, long, double)
139 // __init__(int, char, long)
140 // __init__(int, char)
141 // __init__(int)
142 template <class classT>
143 void visit(classT& cl) const
144 {
145 typedef typename DerivedT::signature signature;
146 typedef typename DerivedT::n_arguments n_arguments;
147 typedef typename DerivedT::n_defaults n_defaults;
148
149 detail::define_class_init_helper<n_defaults::value>::apply(
150 cl
151 , derived().call_policies()
152 , signature()
153 , n_arguments()
154 , derived().doc_string()
155 , derived().keywords());
156 }
157
158 friend class python::def_visitor_access;
159
160 private: // data members
161 char const* m_doc;
162 detail::keyword_range m_keywords;
163};
164
165template <class CallPoliciesT, class InitT>
166class init_with_call_policies
167 : public init_base<init_with_call_policies<CallPoliciesT, InitT> >
168{
169 typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base;
170 public:
171 typedef typename InitT::n_arguments n_arguments;
172 typedef typename InitT::n_defaults n_defaults;
173 typedef typename InitT::signature signature;
174
175 init_with_call_policies(
176 CallPoliciesT const& policies_
177 , char const* doc_
178 , detail::keyword_range const& keywords
179 )
180 : base(doc_, keywords)
181 , m_policies(policies_)
182 {}
183
184 CallPoliciesT const& call_policies() const
185 {
186 return this->m_policies;
187 }
188
189 private: // data members
190 CallPoliciesT m_policies;
191};
192
193//
194// drop1<S> is the initial length(S) elements of S
195//
196namespace detail
197{
198 template <class S>
199 struct drop1
200 : mpl::iterator_range<
201 typename mpl::begin<S>::type
202 , typename mpl::prior<
203 typename mpl::end<S>::type
204 >::type
205 >
206 {};
207}
208
209template <BOOST_PYTHON_OVERLOAD_TYPES>
210class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
211{
212 typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base;
213 public:
214 typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t;
215
216 init(char const* doc_ = 0)
217 : base(doc_)
218 {
219 }
220
221 template <std::size_t N>
222 init(char const* doc_, detail::keywords<N> const& kw)
223 : base(doc_, kw.range())
224 {
225 typedef typename detail::error::more_keywords_than_init_arguments<
226 N, n_arguments::value + 1
227 >::too_many_keywords assertion;
228 }
229
230 template <std::size_t N>
231 init(detail::keywords<N> const& kw, char const* doc_ = 0)
232 : base(doc_, kw.range())
233 {
234 typedef typename detail::error::more_keywords_than_init_arguments<
235 N, n_arguments::value + 1
236 >::too_many_keywords assertion;
237 }
238
239 template <class CallPoliciesT>
240 init_with_call_policies<CallPoliciesT, self_t>
241 operator[](CallPoliciesT const& policies) const
242 {
243 return init_with_call_policies<CallPoliciesT, self_t>(
244 policies, this->doc_string(), this->keywords());
245 }
246
247 typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_;
248
249 typedef detail::is_optional<
250 typename mpl::eval_if<
251 mpl::empty<signature_>
252 , mpl::false_
253 , mpl::back<signature_>
254 >::type
255 > back_is_optional;
256
257 typedef typename mpl::eval_if<
258 back_is_optional
259 , mpl::back<signature_>
260 , mpl::vector0<>
261 >::type optional_args;
262
263 typedef typename mpl::eval_if<
264 back_is_optional
265 , mpl::if_<
266 mpl::empty<optional_args>
267 , detail::drop1<signature_>
268 , mpl::joint_view<
269 detail::drop1<signature_>
270 , optional_args
271 >
272 >
273 , signature_
274 >::type signature;
275
276 // TODO: static assert to make sure there are no other optional elements
277
278 // Count the number of default args
279 typedef mpl::size<optional_args> n_defaults;
280 typedef mpl::size<signature> n_arguments;
281};
282
283///////////////////////////////////////////////////////////////////////////////
284//
285// optional
286//
287// optional<T0...TN>::type returns a typelist.
288//
289///////////////////////////////////////////////////////////////////////////////
290template <BOOST_PYTHON_OVERLOAD_TYPES>
291struct optional
292 : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS>
293{
294};
295
296namespace detail
297{
298 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
299 inline void def_init_aux(
300 ClassT& cl
301 , Signature const&
302 , NArgs
303 , CallPoliciesT const& policies
304 , char const* doc
305 , detail::keyword_range const& keywords_
306 )
307 {
308 cl.def(
309 "__init__"
310 , detail::make_keyword_range_constructor<Signature,NArgs>(
311 policies
312 , keywords_
313 , (typename ClassT::metadata::holder*)0
314 )
315 , doc
316 );
317 }
318
319 ///////////////////////////////////////////////////////////////////////////////
320 //
321 // define_class_init_helper<N>::apply
322 //
323 // General case
324 //
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)
329 //
330 ///////////////////////////////////////////////////////////////////////////////
331 template <int NDefaults>
332 struct define_class_init_helper
333 {
334
335 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
336 static void apply(
337 ClassT& cl
338 , CallPoliciesT const& policies
339 , Signature const& args
340 , NArgs
341 , char const* doc
342 , detail::keyword_range keywords)
343 {
344 detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
345
346 if (keywords.second > keywords.first)
347 --keywords.second;
348
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);
352 }
353 };
354
355 ///////////////////////////////////////////////////////////////////////////////
356 //
357 // define_class_init_helper<0>::apply
358 //
359 // Terminal case
360 //
361 // Accepts a class_ and an arguments list. Defines a constructor
362 // for the class given the arguments.
363 //
364 ///////////////////////////////////////////////////////////////////////////////
365 template <>
366 struct define_class_init_helper<0> {
367
368 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
369 static void apply(
370 ClassT& cl
371 , CallPoliciesT const& policies
372 , Signature const& args
373 , NArgs
374 , char const* doc
375 , detail::keyword_range const& keywords)
376 {
377 detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
378 }
379 };
380}
381
382}} // namespace boost::python
383
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
389
390///////////////////////////////////////////////////////////////////////////////
391#endif // INIT_JDG20020820_HPP
392
393
394
395
396
397
398
399
400

source code of boost/boost/python/init.hpp