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