File indexing completed on 2025-01-18 09:43:31
0001
0002
0003
0004
0005 #ifndef BOOST_PARAMETER_PYTHON_060209_HPP
0006 # define BOOST_PARAMETER_PYTHON_060209_HPP
0007
0008 # include <boost/mpl/vector.hpp>
0009 # include <boost/mpl/fold.hpp>
0010 # include <boost/mpl/prior.hpp>
0011 # include <boost/mpl/shift_right.hpp>
0012 # include <boost/mpl/shift_left.hpp>
0013 # include <boost/mpl/bitand.hpp>
0014 # include <boost/mpl/pair.hpp>
0015 # include <boost/mpl/size.hpp>
0016 # include <boost/mpl/push_back.hpp>
0017 # include <boost/mpl/or.hpp>
0018 # include <boost/mpl/count_if.hpp>
0019 # include <boost/mpl/transform.hpp>
0020 # include <boost/mpl/front.hpp>
0021 # include <boost/mpl/iterator_range.hpp>
0022 # include <boost/mpl/next.hpp>
0023 # include <boost/mpl/begin_end.hpp>
0024 # include <boost/mpl/not.hpp>
0025 # include <boost/mpl/empty.hpp>
0026 # include <boost/python/def.hpp>
0027 # include <boost/python/make_constructor.hpp>
0028 # include <boost/python/init.hpp>
0029 # include <boost/python/to_python_converter.hpp>
0030 # include <boost/parameter/aux_/maybe.hpp>
0031 # include <boost/parameter/aux_/python/invoker.hpp>
0032
0033 namespace boost { namespace parameter { namespace python
0034 {
0035 namespace python_ = boost::python;
0036 }}}
0037
0038 namespace boost { namespace parameter { namespace python { namespace aux
0039 {
0040
0041 inline PyObject* unspecified_type()
0042 {
0043 static PyTypeObject unspecified = {
0044 PyVarObject_HEAD_INIT(NULL,0)
0045 "Boost.Parameter.Unspecified",
0046 PyType_Type.tp_basicsize,
0047 0,
0048 0,
0049 0,
0050 0,
0051 0,
0052 0,
0053 0,
0054 0,
0055 0,
0056 0,
0057 0,
0058 0,
0059 0,
0060 0,
0061 0,
0062 0,
0063 Py_TPFLAGS_DEFAULT,
0064 0,
0065 };
0066
0067 if (Py_TYPE(&unspecified) == 0)
0068 {
0069 Py_TYPE(&unspecified) = &PyType_Type;
0070 PyType_Ready(&unspecified);
0071 }
0072
0073 return (PyObject*)&unspecified;
0074 }
0075
0076 struct empty_tag {};
0077
0078 struct empty_tag_to_python
0079 {
0080 static PyObject* convert(empty_tag)
0081 {
0082 return python_::xincref(unspecified_type());
0083 }
0084 };
0085
0086 }}}}
0087
0088 namespace boost { namespace python
0089 {
0090
0091
0092 template <class T>
0093 struct arg_from_python<parameter::aux::maybe<T> >
0094 : arg_from_python<T>
0095 {
0096 arg_from_python(PyObject* p)
0097 : arg_from_python<T>(p)
0098 , empty(parameter::python::aux::unspecified_type() == p)
0099 {}
0100
0101 bool convertible() const
0102 {
0103 return empty || arg_from_python<T>::convertible();
0104 }
0105
0106 parameter::aux::maybe<T> operator()()
0107 {
0108 if (empty)
0109 {
0110 return parameter::aux::maybe<T>();
0111 }
0112 else
0113 {
0114 return parameter::aux::maybe<T>(
0115 arg_from_python<T>::operator()()
0116 );
0117 }
0118 }
0119
0120 bool empty;
0121 };
0122
0123 }}
0124
0125 namespace boost { namespace parameter { namespace python {
0126
0127 namespace aux
0128 {
0129
0130 template <class K>
0131 struct is_optional
0132 : mpl::not_<
0133 mpl::or_<typename K::required, typename K::optimized_default>
0134 >
0135 {};
0136
0137 template <class K, class Required, class Optimized, class T>
0138 struct arg_spec
0139 {
0140 typedef K keyword;
0141 typedef Required required;
0142 typedef T type;
0143 typedef Optimized optimized_default;
0144 };
0145
0146 template <class K, class T, class Optimized = mpl::false_>
0147 struct make_arg_spec_impl
0148 {
0149 typedef arg_spec<
0150 typename K::first, typename K::second, Optimized, T
0151 > type;
0152 };
0153
0154 template <class K, class T>
0155 struct make_arg_spec_impl<K, T, typename K::third>
0156 {
0157 typedef arg_spec<
0158 typename K::first, typename K::second, typename K::third, T
0159 > type;
0160 };
0161
0162 template <class K, class T>
0163 struct make_arg_spec
0164 : make_arg_spec_impl<K, T>
0165 {
0166 };
0167
0168 template <class Spec, class State>
0169 struct combinations_op
0170 {
0171 typedef typename State::second bits;
0172 typedef typename State::first result0;
0173
0174 typedef typename mpl::if_<
0175 mpl::or_<
0176 typename Spec::required
0177 , typename Spec::optimized_default
0178 , mpl::bitand_<bits, mpl::long_<1> >
0179 >
0180 , typename mpl::push_back<result0, Spec>::type
0181 , result0
0182 >::type result;
0183
0184 typedef typename mpl::if_<
0185 mpl::or_<
0186 typename Spec::required
0187 , typename Spec::optimized_default
0188 >
0189 , bits
0190 , typename mpl::shift_right<bits, mpl::long_<1> >::type
0191 >::type next_bits;
0192
0193 typedef mpl::pair<
0194 result
0195 , next_bits
0196 > type;
0197 };
0198
0199
0200 struct no_keywords
0201 {
0202 template <class T>
0203 T const& operator,(T const& x) const
0204 {
0205 return x;
0206 }
0207 };
0208
0209 template <class Def, class F, class Iter, class End, class Keywords>
0210 void def_combination_aux0(
0211 Def def, F f, Iter, End, Keywords const& keywords, mpl::false_)
0212 {
0213 typedef typename mpl::deref<Iter>::type spec;
0214 typedef typename spec::keyword kw;
0215
0216 def_combination_aux(
0217 def, f, typename mpl::next<Iter>::type(), End()
0218 , (
0219 keywords, boost::python::arg(kw::keyword_name())
0220 )
0221 );
0222 }
0223
0224 template <class Def, class F, class Iter, class End, class Keywords>
0225 void def_combination_aux0(
0226 Def def, F f, Iter, End, Keywords const& keywords, mpl::true_)
0227 {
0228 typedef typename mpl::deref<Iter>::type spec;
0229 typedef typename spec::keyword kw;
0230
0231 def_combination_aux(
0232 def, f, typename mpl::next<Iter>::type(), End()
0233 , (
0234 keywords, boost::python::arg(kw::keyword_name()) = empty_tag()
0235 )
0236 );
0237 }
0238
0239 inline void initialize_converter()
0240 {
0241 static python_::to_python_converter<empty_tag, empty_tag_to_python> x;
0242 }
0243
0244 template <class Def, class F, class Iter, class End, class Keywords>
0245 void def_combination_aux(
0246 Def def, F f, Iter, End, Keywords const& keywords)
0247 {
0248 typedef typename mpl::deref<Iter>::type spec;
0249
0250 typedef typename mpl::and_<
0251 typename spec::optimized_default
0252 , mpl::not_<typename spec::required>
0253 >::type optimized_default;
0254
0255 def_combination_aux0(
0256 def, f, Iter(), End(), keywords, optimized_default()
0257 );
0258 }
0259
0260 template <class Def, class F, class End, class Keywords>
0261 void def_combination_aux(
0262 Def def, F f, End, End, Keywords const& keywords)
0263 {
0264 def(f, keywords);
0265 }
0266
0267 template <class Def, class F, class End>
0268 void def_combination_aux(
0269 Def def, F f, End, End, no_keywords const&)
0270 {
0271 def(f);
0272 }
0273
0274 template <
0275 class Def, class Specs, class Bits, class Invoker
0276 >
0277 void def_combination(
0278 Def def, Specs*, Bits, Invoker*)
0279 {
0280 typedef typename mpl::fold<
0281 Specs
0282 , mpl::pair<mpl::vector0<>, Bits>
0283 , combinations_op<mpl::_2, mpl::_1>
0284 >::type combination0;
0285
0286 typedef typename combination0::first combination;
0287
0288 typedef typename mpl::apply_wrap1<
0289 Invoker, combination
0290 >::type invoker;
0291
0292 def_combination_aux(
0293 def
0294 , &invoker::execute
0295 , typename mpl::begin<combination>::type()
0296 , typename mpl::end<combination>::type()
0297 , no_keywords()
0298 );
0299 }
0300
0301 template <
0302 class Def, class Specs, class Bits, class End, class Invoker
0303 >
0304 void def_combinations(
0305 Def def, Specs*, Bits, End, Invoker*)
0306 {
0307 initialize_converter();
0308
0309 def_combination(def, (Specs*)0, Bits(), (Invoker*)0);
0310
0311 def_combinations(
0312 def
0313 , (Specs*)0
0314 , mpl::long_<Bits::value + 1>()
0315 , End()
0316 , (Invoker*)0
0317 );
0318 }
0319
0320 template <
0321 class Def, class Specs, class End, class Invoker
0322 >
0323 void def_combinations(
0324 Def, Specs*, End, End, Invoker*)
0325 {}
0326
0327 struct not_specified {};
0328
0329 template <class CallPolicies>
0330 struct call_policies_as_options
0331 {
0332 call_policies_as_options(CallPolicies const& call_policies)
0333 : call_policies(call_policies)
0334 {}
0335
0336 CallPolicies const& policies() const
0337 {
0338 return call_policies;
0339 }
0340
0341 char const* doc() const
0342 {
0343 return 0;
0344 }
0345
0346 CallPolicies call_policies;
0347 };
0348
0349 template <class Class, class Options = not_specified>
0350 struct def_class
0351 {
0352 def_class(Class& cl, char const* name, Options options = Options())
0353 : cl(cl)
0354 , name(name)
0355 , options(options)
0356 {}
0357
0358 template <class F>
0359 void def(F f, not_specified const*) const
0360 {
0361 cl.def(name, f);
0362 }
0363
0364 template <class F>
0365 void def(F f, void const*) const
0366 {
0367 cl.def(name, f, options.doc(), options.policies());
0368 }
0369
0370 template <class F>
0371 void operator()(F f) const
0372 {
0373 this->def(f, &options);
0374 }
0375
0376 template <class F, class Keywords>
0377 void def(F f, Keywords const& keywords, not_specified const*) const
0378 {
0379 cl.def(name, f, keywords);
0380 }
0381
0382 template <class F, class Keywords>
0383 void def(F f, Keywords const& keywords, void const*) const
0384 {
0385 cl.def(name, f, keywords, options.doc(), options.policies());
0386 }
0387
0388 template <class F, class Keywords>
0389 void operator()(F f, Keywords const& keywords) const
0390 {
0391 this->def(f, keywords, &options);
0392 }
0393
0394 Class& cl;
0395 char const* name;
0396 Options options;
0397 };
0398
0399 template <class Class, class CallPolicies = boost::python::default_call_policies>
0400 struct def_init
0401 {
0402 def_init(Class& cl, CallPolicies call_policies = CallPolicies())
0403 : cl(cl)
0404 , call_policies(call_policies)
0405 {}
0406
0407 template <class F>
0408 void operator()(F f) const
0409 {
0410 cl.def(
0411 "__init__"
0412 , boost::python::make_constructor(f, call_policies)
0413 );
0414 }
0415
0416 template <class F, class Keywords>
0417 void operator()(F f, Keywords const& keywords) const
0418 {
0419 cl.def(
0420 "__init__"
0421 , boost::python::make_constructor(f, call_policies, keywords)
0422 );
0423 }
0424
0425 Class& cl;
0426 CallPolicies call_policies;
0427 };
0428
0429 struct def_function
0430 {
0431 def_function(char const* name)
0432 : name(name)
0433 {}
0434
0435 template <class F>
0436 void operator()(F f) const
0437 {
0438 boost::python::def(name, f);
0439 }
0440
0441 template <class F, class Keywords>
0442 void operator()(F f, Keywords const& keywords) const
0443 {
0444 boost::python::def(name, f, keywords);
0445 }
0446
0447 char const* name;
0448 };
0449
0450 }
0451
0452 template <class M, class Signature>
0453 void def(char const* name, Signature)
0454 {
0455 typedef mpl::iterator_range<
0456 typename mpl::next<
0457 typename mpl::begin<Signature>::type
0458 >::type
0459 , typename mpl::end<Signature>::type
0460 > arg_types;
0461
0462 typedef typename mpl::transform<
0463 typename M::keywords
0464 , arg_types
0465 , aux::make_arg_spec<mpl::_1, mpl::_2>
0466 , mpl::back_inserter<mpl::vector0<> >
0467 >::type arg_specs;
0468
0469 typedef typename mpl::count_if<
0470 arg_specs
0471 , aux::is_optional<mpl::_1>
0472 >::type optional_arity;
0473
0474 typedef typename mpl::front<Signature>::type result_type;
0475 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0476
0477 aux::def_combinations(
0478 aux::def_function(name)
0479 , (arg_specs*)0
0480 , mpl::long_<0>()
0481 , mpl::long_<upper::value>()
0482 , (aux::make_invoker<M, result_type>*)0
0483 );
0484 }
0485
0486 template <class M, class Class, class Signature>
0487 void def(Class& cl, char const* name, Signature)
0488 {
0489 typedef mpl::iterator_range<
0490 typename mpl::next<
0491 typename mpl::begin<Signature>::type
0492 >::type
0493 , typename mpl::end<Signature>::type
0494 > arg_types;
0495
0496 typedef typename mpl::transform<
0497 typename M::keywords
0498 , arg_types
0499 , aux::make_arg_spec<mpl::_1, mpl::_2>
0500 , mpl::back_inserter<mpl::vector0<> >
0501 >::type arg_specs;
0502
0503 typedef typename mpl::count_if<
0504 arg_specs
0505 , aux::is_optional<mpl::_1>
0506 >::type optional_arity;
0507
0508 typedef typename mpl::front<Signature>::type result_type;
0509 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0510
0511 aux::def_combinations(
0512 aux::def_class<Class>(cl, name)
0513 , (arg_specs*)0
0514 , mpl::long_<0>()
0515 , mpl::long_<upper::value>()
0516 , (aux::make_invoker<M, result_type>*)0
0517 );
0518 }
0519
0520 namespace aux
0521 {
0522
0523 template <class K>
0524 struct keyword
0525 {
0526 typedef K type;
0527 };
0528
0529 template <class K>
0530 struct keyword<K*>
0531 {
0532 typedef K type;
0533 };
0534
0535 template <class K>
0536 struct keyword<K**>
0537 {
0538 typedef K type;
0539 };
0540
0541 template <class K>
0542 struct required
0543 {
0544 typedef mpl::true_ type;
0545 };
0546
0547 template <class K>
0548 struct required<K*>
0549 {
0550 typedef mpl::false_ type;
0551 };
0552
0553 template <class K>
0554 struct optimized
0555 {
0556 typedef mpl::true_ type;
0557 };
0558
0559 template <class K>
0560 struct optimized<K**>
0561 {
0562 typedef mpl::false_ type;
0563 };
0564
0565 template <class T>
0566 struct make_kw_spec;
0567
0568 template <class K, class T>
0569 struct make_kw_spec<K(T)>
0570 {
0571 typedef arg_spec<
0572 typename keyword<K>::type
0573 , typename required<K>::type
0574 , typename optimized<K>::type
0575 , T
0576 > type;
0577 };
0578
0579 }
0580
0581 template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>
0582 struct init
0583 : boost::python::def_visitor<init<ParameterSpecs, CallPolicies> >
0584 {
0585 init(CallPolicies call_policies = CallPolicies())
0586 : call_policies(call_policies)
0587 {}
0588
0589 template <class CallPolicies1>
0590 init<ParameterSpecs, CallPolicies1>
0591 operator[](CallPolicies1 const& call_policies) const
0592 {
0593 return init<ParameterSpecs, CallPolicies1>(call_policies);
0594 }
0595
0596 template <class Class>
0597 void visit_aux(Class& cl, mpl::true_) const
0598 {
0599 cl.def(boost::python::init<>()[call_policies]);
0600 }
0601
0602 template <class Class>
0603 void visit_aux(Class& cl, mpl::false_) const
0604 {
0605 typedef typename mpl::transform<
0606 ParameterSpecs
0607 , aux::make_kw_spec<mpl::_>
0608 , mpl::back_inserter<mpl::vector0<> >
0609 >::type arg_specs;
0610
0611 typedef typename mpl::count_if<
0612 arg_specs
0613 , aux::is_optional<mpl::_>
0614 >::type optional_arity;
0615
0616 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0617
0618 aux::def_combinations(
0619 aux::def_init<Class, CallPolicies>(cl, call_policies)
0620 , (arg_specs*)0
0621 , mpl::long_<0>()
0622 , mpl::long_<upper::value>()
0623 , (aux::make_init_invoker<typename Class::wrapped_type>*)0
0624 );
0625 }
0626
0627 template <class Class>
0628 void visit(Class& cl) const
0629 {
0630 visit_aux(cl, mpl::empty<ParameterSpecs>());
0631 }
0632
0633 CallPolicies call_policies;
0634 };
0635
0636 template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>
0637 struct call
0638 : boost::python::def_visitor<call<ParameterSpecs, CallPolicies> >
0639 {
0640 call(CallPolicies const& call_policies = CallPolicies())
0641 : call_policies(call_policies)
0642 {}
0643
0644 template <class CallPolicies1>
0645 call<ParameterSpecs, CallPolicies1>
0646 operator[](CallPolicies1 const& call_policies) const
0647 {
0648 return call<ParameterSpecs, CallPolicies1>(call_policies);
0649 }
0650
0651 template <class Class>
0652 void visit(Class& cl) const
0653 {
0654 typedef mpl::iterator_range<
0655 typename mpl::next<
0656 typename mpl::begin<ParameterSpecs>::type
0657 >::type
0658 , typename mpl::end<ParameterSpecs>::type
0659 > arg_types;
0660
0661 typedef typename mpl::front<ParameterSpecs>::type result_type;
0662
0663 typedef typename mpl::transform<
0664 arg_types
0665 , aux::make_kw_spec<mpl::_>
0666 , mpl::back_inserter<mpl::vector0<> >
0667 >::type arg_specs;
0668
0669 typedef typename mpl::count_if<
0670 arg_specs
0671 , aux::is_optional<mpl::_>
0672 >::type optional_arity;
0673
0674 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0675
0676 typedef aux::call_policies_as_options<CallPolicies> options;
0677
0678 aux::def_combinations(
0679 aux::def_class<Class, options>(cl, "__call__", options(call_policies))
0680 , (arg_specs*)0
0681 , mpl::long_<0>()
0682 , mpl::long_<upper::value>()
0683 , (aux::make_call_invoker<typename Class::wrapped_type, result_type>*)0
0684 );
0685 }
0686
0687 CallPolicies call_policies;
0688 };
0689
0690 template <class Fwd, class ParameterSpecs>
0691 struct function
0692 : boost::python::def_visitor<function<Fwd, ParameterSpecs> >
0693 {
0694 template <class Class, class Options>
0695 void visit(Class& cl, char const* name, Options const& options) const
0696 {
0697 typedef mpl::iterator_range<
0698 typename mpl::next<
0699 typename mpl::begin<ParameterSpecs>::type
0700 >::type
0701 , typename mpl::end<ParameterSpecs>::type
0702 > arg_types;
0703
0704 typedef typename mpl::front<ParameterSpecs>::type result_type;
0705
0706 typedef typename mpl::transform<
0707 arg_types
0708 , aux::make_kw_spec<mpl::_>
0709 , mpl::back_inserter<mpl::vector0<> >
0710 >::type arg_specs;
0711
0712 typedef typename mpl::count_if<
0713 arg_specs
0714 , aux::is_optional<mpl::_>
0715 >::type optional_arity;
0716
0717 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0718
0719 aux::def_combinations(
0720 aux::def_class<Class, Options>(cl, name, options)
0721 , (arg_specs*)0
0722 , mpl::long_<0>()
0723 , mpl::long_<upper::value>()
0724 , (aux::make_member_invoker<
0725 Fwd, result_type, typename Class::wrapped_type
0726 >*)0
0727 );
0728 }
0729 };
0730
0731 }}}
0732
0733 #endif
0734