1 // Copyright Daniel Wallin 2006. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef BOOST_PARAMETER_PYTHON_060209_HPP
6 # define BOOST_PARAMETER_PYTHON_060209_HPP
8 # include <boost/mpl/vector.hpp>
9 # include <boost/mpl/fold.hpp>
10 # include <boost/mpl/prior.hpp>
11 # include <boost/mpl/shift_right.hpp>
12 # include <boost/mpl/shift_left.hpp>
13 # include <boost/mpl/bitand.hpp>
14 # include <boost/mpl/pair.hpp>
15 # include <boost/mpl/size.hpp>
16 # include <boost/mpl/push_back.hpp>
17 # include <boost/mpl/or.hpp>
18 # include <boost/mpl/count_if.hpp>
19 # include <boost/mpl/transform.hpp>
20 # include <boost/mpl/front.hpp>
21 # include <boost/mpl/iterator_range.hpp>
22 # include <boost/mpl/next.hpp>
23 # include <boost/mpl/begin_end.hpp>
24 # include <boost/mpl/not.hpp>
25 # include <boost/mpl/empty.hpp>
26 # include <boost/python/def.hpp>
27 # include <boost/python/make_constructor.hpp>
28 # include <boost/python/init.hpp>
29 # include <boost/python/to_python_converter.hpp>
30 # include <boost/parameter/aux_/maybe.hpp>
31 # include <boost/parameter/aux_/python/invoker.hpp>
33 namespace boost
{ namespace parameter
{ namespace python
35 namespace python_
= boost::python
;
38 namespace boost
{ namespace parameter
{ namespace python
{ namespace aux
41 inline PyObject
* unspecified_type()
43 static PyTypeObject unspecified
= {
44 PyObject_HEAD_INIT(NULL
)
46 "Boost.Parameter.Unspecified", /* tp_name */
47 PyType_Type
.tp_basicsize
, /* tp_basicsize */
56 0, /* tp_as_sequence */
57 0, /* tp_as_mapping */
64 Py_TPFLAGS_DEFAULT
, /* tp_flags */
68 if (unspecified
.ob_type
== 0)
70 unspecified
.ob_type
= &PyType_Type
;
71 PyType_Ready(&unspecified
);
74 return (PyObject
*)&unspecified
;
79 struct empty_tag_to_python
81 static PyObject
* convert(empty_tag
)
83 return python_::xincref(unspecified_type());
87 }}}} // namespace boost::parameter::python::aux
89 namespace boost
{ namespace python
92 // Converts a Python value to a maybe<T>
94 struct arg_from_python
<parameter::aux::maybe
<T
> >
97 arg_from_python(PyObject
* p
)
98 : arg_from_python
<T
>(p
)
99 , empty(parameter::python::aux::unspecified_type() == p
)
102 bool convertible() const
104 return empty
|| arg_from_python
<T
>::convertible();
107 parameter::aux::maybe
<T
> operator()()
111 return parameter::aux::maybe
<T
>();
115 return parameter::aux::maybe
<T
>(
116 arg_from_python
<T
>::operator()()
124 }} // namespace boost::python
126 namespace boost
{ namespace parameter
{ namespace python
{
134 mpl::or_
<typename
K::required
, typename
K::optimized_default
>
138 template <class K
, class Required
, class Optimized
, class T
>
142 typedef Required required
;
144 typedef Optimized optimized_default
;
147 template <class K
, class T
, class Optimized
= mpl::false_
>
148 struct make_arg_spec_impl
151 typename
K::first
, typename
K::second
, Optimized
, T
155 template <class K
, class T
>
156 struct make_arg_spec_impl
<K
, T
, typename
K::third
>
159 typename
K::first
, typename
K::second
, typename
K::third
, T
163 template <class K
, class T
>
165 : make_arg_spec_impl
<K
, T
>
169 template <class Spec
, class State
>
170 struct combinations_op
172 typedef typename
State::second bits
;
173 typedef typename
State::first result0
;
175 typedef typename
mpl::if_
<
177 typename
Spec::required
178 , typename
Spec::optimized_default
179 , mpl::bitand_
<bits
, mpl::long_
<1> >
181 , typename
mpl::push_back
<result0
, Spec
>::type
185 typedef typename
mpl::if_
<
187 typename
Spec::required
188 , typename
Spec::optimized_default
191 , typename
mpl::shift_right
<bits
, mpl::long_
<1> >::type
200 // Used as start value in the recursive arg() composition below.
204 T
const& operator,(T
const& x
) const
210 template <class Def
, class F
, class Iter
, class End
, class Keywords
>
211 void def_combination_aux0(
212 Def def
, F f
, Iter
, End
, Keywords
const& keywords
, mpl::false_
)
214 typedef typename
mpl::deref
<Iter
>::type spec
;
215 typedef typename
spec::keyword kw
;
218 def
, f
, typename
mpl::next
<Iter
>::type(), End()
220 keywords
, boost::python::arg(kw::keyword_name())
225 template <class Def
, class F
, class Iter
, class End
, class Keywords
>
226 void def_combination_aux0(
227 Def def
, F f
, Iter
, End
, Keywords
const& keywords
, mpl::true_
)
229 typedef typename
mpl::deref
<Iter
>::type spec
;
230 typedef typename
spec::keyword kw
;
233 def
, f
, typename
mpl::next
<Iter
>::type(), End()
235 keywords
, boost::python::arg(kw::keyword_name()) = empty_tag()
240 inline void initialize_converter()
242 static python_::to_python_converter
<empty_tag
, empty_tag_to_python
> x
;
245 template <class Def
, class F
, class Iter
, class End
, class Keywords
>
246 void def_combination_aux(
247 Def def
, F f
, Iter
, End
, Keywords
const& keywords
)
249 typedef typename
mpl::deref
<Iter
>::type spec
;
251 typedef typename
mpl::and_
<
252 typename
spec::optimized_default
253 , mpl::not_
<typename
spec::required
>
254 >::type optimized_default
;
256 def_combination_aux0(
257 def
, f
, Iter(), End(), keywords
, optimized_default()
261 template <class Def
, class F
, class End
, class Keywords
>
262 void def_combination_aux(
263 Def def
, F f
, End
, End
, Keywords
const& keywords
)
268 template <class Def
, class F
, class End
>
269 void def_combination_aux(
270 Def def
, F f
, End
, End
, no_keywords
const&)
276 class Def
, class Specs
, class Bits
, class Invoker
278 void def_combination(
279 Def def
, Specs
*, Bits
, Invoker
*)
281 typedef typename
mpl::fold
<
283 , mpl::pair
<mpl::vector0
<>, Bits
>
284 , combinations_op
<mpl::_2
, mpl::_1
>
285 >::type combination0
;
287 typedef typename
combination0::first combination
;
289 typedef typename
mpl::apply_wrap1
<
296 , typename
mpl::begin
<combination
>::type()
297 , typename
mpl::end
<combination
>::type()
303 class Def
, class Specs
, class Bits
, class End
, class Invoker
305 void def_combinations(
306 Def def
, Specs
*, Bits
, End
, Invoker
*)
308 initialize_converter();
310 def_combination(def
, (Specs
*)0, Bits(), (Invoker
*)0);
315 , mpl::long_
<Bits::value
+ 1>()
322 class Def
, class Specs
, class End
, class Invoker
324 void def_combinations(
325 Def
, Specs
*, End
, End
, Invoker
*)
328 struct not_specified
{};
330 template <class CallPolicies
>
331 struct call_policies_as_options
333 call_policies_as_options(CallPolicies
const& call_policies
)
334 : call_policies(call_policies
)
337 CallPolicies
const& policies() const
339 return call_policies
;
342 char const* doc() const
347 CallPolicies call_policies
;
350 template <class Class
, class Options
= not_specified
>
353 def_class(Class
& cl
, char const* name
, Options options
= Options())
360 void def(F f
, not_specified
const*) const
366 void def(F f
, void const*) const
368 cl
.def(name
, f
, options
.doc(), options
.policies());
372 void operator()(F f
) const
374 this->def(f
, &options
);
377 template <class F
, class Keywords
>
378 void def(F f
, Keywords
const& keywords
, not_specified
const*) const
380 cl
.def(name
, f
, keywords
);
383 template <class F
, class Keywords
>
384 void def(F f
, Keywords
const& keywords
, void const*) const
386 cl
.def(name
, f
, keywords
, options
.doc(), options
.policies());
389 template <class F
, class Keywords
>
390 void operator()(F f
, Keywords
const& keywords
) const
392 this->def(f
, keywords
, &options
);
400 template <class Class
, class CallPolicies
= boost::python::default_call_policies
>
403 def_init(Class
& cl
, CallPolicies call_policies
= CallPolicies())
405 , call_policies(call_policies
)
409 void operator()(F f
) const
413 , boost::python::make_constructor(f
, call_policies
)
417 template <class F
, class Keywords
>
418 void operator()(F f
, Keywords
const& keywords
) const
422 , boost::python::make_constructor(f
, call_policies
, keywords
)
427 CallPolicies call_policies
;
432 def_function(char const* name
)
437 void operator()(F f
) const
439 boost::python::def(name
, f
);
442 template <class F
, class Keywords
>
443 void operator()(F f
, Keywords
const& keywords
) const
445 boost::python::def(name
, f
, keywords
);
453 template <class M
, class Signature
>
454 void def(char const* name
, Signature
)
456 typedef mpl::iterator_range
<
458 typename
mpl::begin
<Signature
>::type
460 , typename
mpl::end
<Signature
>::type
463 typedef typename
mpl::transform
<
466 , aux::make_arg_spec
<mpl::_1
, mpl::_2
>
467 , mpl::back_inserter
<mpl::vector0
<> >
470 typedef typename
mpl::count_if
<
472 , aux::is_optional
<mpl::_1
>
473 >::type optional_arity
;
475 typedef typename
mpl::front
<Signature
>::type result_type
;
476 typedef typename
mpl::shift_left
<mpl::long_
<1>, optional_arity
>::type upper
;
478 aux::def_combinations(
479 aux::def_function(name
)
482 , mpl::long_
<upper::value
>()
483 , (aux::make_invoker
<M
, result_type
>*)0
487 template <class M
, class Class
, class Signature
>
488 void def(Class
& cl
, char const* name
, Signature
)
490 typedef mpl::iterator_range
<
492 typename
mpl::begin
<Signature
>::type
494 , typename
mpl::end
<Signature
>::type
497 typedef typename
mpl::transform
<
500 , aux::make_arg_spec
<mpl::_1
, mpl::_2
>
501 , mpl::back_inserter
<mpl::vector0
<> >
504 typedef typename
mpl::count_if
<
506 , aux::is_optional
<mpl::_1
>
507 >::type optional_arity
;
509 typedef typename
mpl::front
<Signature
>::type result_type
;
510 typedef typename
mpl::shift_left
<mpl::long_
<1>, optional_arity
>::type upper
;
512 aux::def_combinations(
513 aux::def_class
<Class
>(cl
, name
)
516 , mpl::long_
<upper::value
>()
517 , (aux::make_invoker
<M
, result_type
>*)0
545 typedef mpl::true_ type
;
551 typedef mpl::false_ type
;
557 typedef mpl::true_ type
;
561 struct optimized
<K
**>
563 typedef mpl::false_ type
;
569 template <class K
, class T
>
570 struct make_kw_spec
<K(T
)>
573 typename keyword
<K
>::type
574 , typename required
<K
>::type
575 , typename optimized
<K
>::type
582 template <class ParameterSpecs
, class CallPolicies
= boost::python::default_call_policies
>
584 : boost::python::def_visitor
<init
<ParameterSpecs
, CallPolicies
> >
586 init(CallPolicies call_policies
= CallPolicies())
587 : call_policies(call_policies
)
590 template <class CallPolicies1
>
591 init
<ParameterSpecs
, CallPolicies1
>
592 operator[](CallPolicies1
const& call_policies
) const
594 return init
<ParameterSpecs
, CallPolicies1
>(call_policies
);
597 template <class Class
>
598 void visit_aux(Class
& cl
, mpl::true_
) const
600 cl
.def(boost::python::init
<>()[call_policies
]);
603 template <class Class
>
604 void visit_aux(Class
& cl
, mpl::false_
) const
606 typedef typename
mpl::transform
<
608 , aux::make_kw_spec
<mpl::_
>
609 , mpl::back_inserter
<mpl::vector0
<> >
612 typedef typename
mpl::count_if
<
614 , aux::is_optional
<mpl::_
>
615 >::type optional_arity
;
617 typedef typename
mpl::shift_left
<mpl::long_
<1>, optional_arity
>::type upper
;
619 aux::def_combinations(
620 aux::def_init
<Class
, CallPolicies
>(cl
, call_policies
)
623 , mpl::long_
<upper::value
>()
624 , (aux::make_init_invoker
<typename
Class::wrapped_type
>*)0
628 template <class Class
>
629 void visit(Class
& cl
) const
631 visit_aux(cl
, mpl::empty
<ParameterSpecs
>());
634 CallPolicies call_policies
;
637 template <class ParameterSpecs
, class CallPolicies
= boost::python::default_call_policies
>
639 : boost::python::def_visitor
<call
<ParameterSpecs
, CallPolicies
> >
641 call(CallPolicies
const& call_policies
= CallPolicies())
642 : call_policies(call_policies
)
645 template <class CallPolicies1
>
646 call
<ParameterSpecs
, CallPolicies1
>
647 operator[](CallPolicies1
const& call_policies
) const
649 return call
<ParameterSpecs
, CallPolicies1
>(call_policies
);
652 template <class Class
>
653 void visit(Class
& cl
) const
655 typedef mpl::iterator_range
<
657 typename
mpl::begin
<ParameterSpecs
>::type
659 , typename
mpl::end
<ParameterSpecs
>::type
662 typedef typename
mpl::front
<ParameterSpecs
>::type result_type
;
664 typedef typename
mpl::transform
<
666 , aux::make_kw_spec
<mpl::_
>
667 , mpl::back_inserter
<mpl::vector0
<> >
670 typedef typename
mpl::count_if
<
672 , aux::is_optional
<mpl::_
>
673 >::type optional_arity
;
675 typedef typename
mpl::shift_left
<mpl::long_
<1>, optional_arity
>::type upper
;
677 typedef aux::call_policies_as_options
<CallPolicies
> options
;
679 aux::def_combinations(
680 aux::def_class
<Class
, options
>(cl
, "__call__", options(call_policies
))
683 , mpl::long_
<upper::value
>()
684 , (aux::make_call_invoker
<typename
Class::wrapped_type
, result_type
>*)0
688 CallPolicies call_policies
;
691 template <class Fwd
, class ParameterSpecs
>
693 : boost::python::def_visitor
<function
<Fwd
, ParameterSpecs
> >
695 template <class Class
, class Options
>
696 void visit(Class
& cl
, char const* name
, Options
const& options
) const
698 typedef mpl::iterator_range
<
700 typename
mpl::begin
<ParameterSpecs
>::type
702 , typename
mpl::end
<ParameterSpecs
>::type
705 typedef typename
mpl::front
<ParameterSpecs
>::type result_type
;
707 typedef typename
mpl::transform
<
709 , aux::make_kw_spec
<mpl::_
>
710 , mpl::back_inserter
<mpl::vector0
<> >
713 typedef typename
mpl::count_if
<
715 , aux::is_optional
<mpl::_
>
716 >::type optional_arity
;
718 typedef typename
mpl::shift_left
<mpl::long_
<1>, optional_arity
>::type upper
;
720 aux::def_combinations(
721 aux::def_class
<Class
, Options
>(cl
, name
, options
)
724 , mpl::long_
<upper::value
>()
725 , (aux::make_member_invoker
<
726 Fwd
, result_type
, typename
Class::wrapped_type
732 }}} // namespace boost::parameter::python
734 #endif // BOOST_PARAMETER_PYTHON_060209_HPP