| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734 | // Copyright Daniel Wallin 2006. Use, modification and distribution is// subject to the Boost Software License, Version 1.0. (See accompanying// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)#ifndef BOOST_PARAMETER_PYTHON_060209_HPP# define BOOST_PARAMETER_PYTHON_060209_HPP# include <boost/mpl/vector.hpp># include <boost/mpl/fold.hpp># include <boost/mpl/prior.hpp># include <boost/mpl/shift_right.hpp># include <boost/mpl/shift_left.hpp># include <boost/mpl/bitand.hpp># include <boost/mpl/pair.hpp># include <boost/mpl/size.hpp># include <boost/mpl/push_back.hpp># include <boost/mpl/or.hpp># include <boost/mpl/count_if.hpp># include <boost/mpl/transform.hpp># include <boost/mpl/front.hpp># include <boost/mpl/iterator_range.hpp># include <boost/mpl/next.hpp># include <boost/mpl/begin_end.hpp># include <boost/mpl/not.hpp># include <boost/mpl/empty.hpp># include <boost/python/def.hpp># include <boost/python/make_constructor.hpp># include <boost/python/init.hpp># include <boost/python/to_python_converter.hpp># include <boost/parameter/aux_/maybe.hpp># include <boost/parameter/aux_/python/invoker.hpp>namespace boost { namespace parameter { namespace python {  namespace python_ = boost::python;}}}namespace boost { namespace parameter { namespace python { namespace aux {  inline PyObject* unspecified_type()  {      static PyTypeObject unspecified = {          PyVarObject_HEAD_INIT(NULL,0)          "Boost.Parameter.Unspecified",    /* tp_name        */          PyType_Type.tp_basicsize,         /* tp_basicsize   */          0,                                /* tp_itemsize    */          0,                                /* tp_dealloc     */          0,                                /* tp_print       */          0,                                /* tp_getattr     */          0,                                /* tp_setattr     */          0,                                /* tp_compare     */          0,                                /* tp_repr        */          0,                                /* tp_as_number   */          0,                                /* tp_as_sequence */          0,                                /* tp_as_mapping  */          0,                                /* tp_hash        */          0,                                /* tp_call        */          0,                                /* tp_str         */          0,                                /* tp_getattro    */          0,                                /* tp_setattro    */          0,                                /* tp_as_buffer   */          Py_TPFLAGS_DEFAULT,               /* tp_flags       */          0,                                /* tp_doc         */      };            if (Py_TYPE(&unspecified) == 0)      {          Py_TYPE(&unspecified) = &PyType_Type;          PyType_Ready(&unspecified);      }            return (PyObject*)&unspecified;  }  struct empty_tag {};  struct empty_tag_to_python  {      static PyObject* convert(empty_tag)      {          return python_::xincref(unspecified_type());      }  };}}}} // namespace boost::parameter::python::auxnamespace boost { namespace python {  // Converts a Python value to a maybe<T>  template <class T>  struct arg_from_python<parameter::aux::maybe<T> >    : arg_from_python<T>  {      arg_from_python(PyObject* p)        : arg_from_python<T>(p)        , empty(parameter::python::aux::unspecified_type() == p)      {}      bool convertible() const      {          return empty || arg_from_python<T>::convertible();      }      parameter::aux::maybe<T> operator()()      {          if (empty)          {              return parameter::aux::maybe<T>();          }          else          {              return parameter::aux::maybe<T>(                  arg_from_python<T>::operator()()              );          }      }      bool empty;  };}} // namespace boost::pythonnamespace boost { namespace parameter { namespace python {namespace aux{  template <class K>  struct is_optional    : mpl::not_<          mpl::or_<typename K::required, typename K::optimized_default>      >  {};  template <class K, class Required, class Optimized, class T>  struct arg_spec  {      typedef K keyword;      typedef Required required;      typedef T type;      typedef Optimized optimized_default;  };    template <class K, class T, class Optimized = mpl::false_>  struct make_arg_spec_impl  {      typedef arg_spec<          typename K::first, typename K::second, Optimized, T      > type;  };  template <class K, class T>  struct make_arg_spec_impl<K, T, typename K::third>  {      typedef arg_spec<          typename K::first, typename K::second, typename K::third, T      > type;  };  template <class K, class T>  struct make_arg_spec    : make_arg_spec_impl<K, T>  {  };  template <class Spec, class State>  struct combinations_op  {      typedef typename State::second bits;      typedef typename State::first result0;      typedef typename mpl::if_<          mpl::or_<              typename Spec::required            , typename Spec::optimized_default            , mpl::bitand_<bits, mpl::long_<1> >          >        , typename mpl::push_back<result0, Spec>::type        , result0      >::type result;      typedef typename mpl::if_<          mpl::or_<              typename Spec::required            , typename Spec::optimized_default          >        , bits        , typename mpl::shift_right<bits, mpl::long_<1> >::type      >::type next_bits;      typedef mpl::pair<          result        , next_bits      > type;  };  // Used as start value in the recursive arg() composition below.  struct no_keywords  {      template <class T>      T const& operator,(T const& x) const      {          return x;      }  };  template <class Def, class F, class Iter, class End, class Keywords>  void def_combination_aux0(      Def def, F f, Iter, End, Keywords const& keywords, mpl::false_)  {      typedef typename mpl::deref<Iter>::type spec;      typedef typename spec::keyword kw;      def_combination_aux(          def, f, typename mpl::next<Iter>::type(), End()        , (              keywords, boost::python::arg(kw::keyword_name())          )      );  }  template <class Def, class F, class Iter, class End, class Keywords>  void def_combination_aux0(      Def def, F f, Iter, End, Keywords const& keywords, mpl::true_)  {      typedef typename mpl::deref<Iter>::type spec;      typedef typename spec::keyword kw;      def_combination_aux(          def, f, typename mpl::next<Iter>::type(), End()        , (              keywords, boost::python::arg(kw::keyword_name()) = empty_tag()          )      );  }  inline void initialize_converter()  {      static python_::to_python_converter<empty_tag, empty_tag_to_python> x;  }  template <class Def, class F, class Iter, class End, class Keywords>  void def_combination_aux(      Def def, F f, Iter, End, Keywords const& keywords)  {      typedef typename mpl::deref<Iter>::type spec;      typedef typename mpl::and_<          typename spec::optimized_default        , mpl::not_<typename spec::required>      >::type optimized_default;            def_combination_aux0(          def, f, Iter(), End(), keywords, optimized_default()      );  }  template <class Def, class F, class End, class Keywords>  void def_combination_aux(      Def def, F f, End, End, Keywords const& keywords)  {      def(f, keywords);  }   template <class Def, class F, class End>  void def_combination_aux(      Def def, F f, End, End, no_keywords const&)  {      def(f);  }  template <      class Def, class Specs, class Bits, class Invoker  >  void def_combination(      Def def, Specs*, Bits, Invoker*)  {      typedef typename mpl::fold<          Specs        , mpl::pair<mpl::vector0<>, Bits>        , combinations_op<mpl::_2, mpl::_1>      >::type combination0;      typedef typename combination0::first combination;      typedef typename mpl::apply_wrap1<          Invoker, combination      >::type invoker;      def_combination_aux(          def        , &invoker::execute        , typename mpl::begin<combination>::type()        , typename mpl::end<combination>::type()        , no_keywords()      );  }  template <      class Def, class Specs, class Bits, class End, class Invoker  >  void def_combinations(      Def def, Specs*, Bits, End, Invoker*)  {      initialize_converter();      def_combination(def, (Specs*)0, Bits(), (Invoker*)0);      def_combinations(          def        , (Specs*)0        , mpl::long_<Bits::value + 1>()        , End()        , (Invoker*)0      );  }  template <      class Def, class Specs, class End, class Invoker  >  void def_combinations(      Def, Specs*, End, End, Invoker*)  {}  struct not_specified {};  template <class CallPolicies>  struct call_policies_as_options  {      call_policies_as_options(CallPolicies const& call_policies)        : call_policies(call_policies)      {}      CallPolicies const& policies() const      {          return call_policies;      }      char const* doc() const      {          return 0;      }      CallPolicies call_policies;  };  template <class Class, class Options = not_specified>  struct def_class  {      def_class(Class& cl, char const* name, Options options = Options())        : cl(cl)        , name(name)        , options(options)      {}      template <class F>      void def(F f, not_specified const*) const      {          cl.def(name, f);      }      template <class F>      void def(F f, void const*) const      {          cl.def(name, f, options.doc(), options.policies());      }            template <class F>      void operator()(F f) const      {          this->def(f, &options);      }      template <class F, class Keywords>      void def(F f, Keywords const& keywords, not_specified const*) const      {          cl.def(name, f, keywords);      }      template <class F, class Keywords>      void def(F f, Keywords const& keywords, void const*) const      {          cl.def(name, f, keywords, options.doc(), options.policies());      }      template <class F, class Keywords>      void operator()(F f, Keywords const& keywords) const      {          this->def(f, keywords, &options);      }      Class& cl;      char const* name;      Options options;  };  template <class Class, class CallPolicies = boost::python::default_call_policies>  struct def_init  {      def_init(Class& cl, CallPolicies call_policies = CallPolicies())        : cl(cl)        , call_policies(call_policies)      {}      template <class F>      void operator()(F f) const      {          cl.def(              "__init__"            , boost::python::make_constructor(f, call_policies)          );      }      template <class F, class Keywords>      void operator()(F f, Keywords const& keywords) const      {          cl.def(              "__init__"            , boost::python::make_constructor(f, call_policies, keywords)          );      }      Class& cl;      CallPolicies call_policies;  };  struct def_function  {      def_function(char const* name)        : name(name)      {}            template <class F>      void operator()(F f) const      {          boost::python::def(name, f);      }      template <class F, class Keywords>      void operator()(F f, Keywords const& keywords) const      {          boost::python::def(name, f, keywords);      }      char const* name;  };} // namespace auxtemplate <class M, class Signature>void def(char const* name, Signature){    typedef mpl::iterator_range<        typename mpl::next<            typename mpl::begin<Signature>::type        >::type      , typename mpl::end<Signature>::type    > arg_types;    typedef typename mpl::transform<        typename M::keywords      , arg_types      , aux::make_arg_spec<mpl::_1, mpl::_2>      , mpl::back_inserter<mpl::vector0<> >    >::type arg_specs;    typedef typename mpl::count_if<        arg_specs      , aux::is_optional<mpl::_1>    >::type optional_arity;        typedef typename mpl::front<Signature>::type result_type;    typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;    aux::def_combinations(        aux::def_function(name)      , (arg_specs*)0      , mpl::long_<0>()      , mpl::long_<upper::value>()      , (aux::make_invoker<M, result_type>*)0    );}template <class M, class Class, class Signature>void def(Class& cl, char const* name, Signature){    typedef mpl::iterator_range<        typename mpl::next<            typename mpl::begin<Signature>::type        >::type      , typename mpl::end<Signature>::type    > arg_types;    typedef typename mpl::transform<        typename M::keywords      , arg_types      , aux::make_arg_spec<mpl::_1, mpl::_2>      , mpl::back_inserter<mpl::vector0<> >    >::type arg_specs;    typedef typename mpl::count_if<        arg_specs      , aux::is_optional<mpl::_1>    >::type optional_arity;        typedef typename mpl::front<Signature>::type result_type;    typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;    aux::def_combinations(        aux::def_class<Class>(cl, name)      , (arg_specs*)0      , mpl::long_<0>()      , mpl::long_<upper::value>()      , (aux::make_invoker<M, result_type>*)0    );}namespace aux{  template <class K>  struct keyword  {      typedef K type;  };  template <class K>  struct keyword<K*>  {      typedef K type;  };  template <class K>  struct keyword<K**>  {      typedef K type;  };  template <class K>  struct required  {      typedef mpl::true_ type;  };  template <class K>  struct required<K*>  {      typedef mpl::false_ type;  };  template <class K>  struct optimized  {      typedef mpl::true_ type;  };  template <class K>  struct optimized<K**>  {      typedef mpl::false_ type;  };  template <class T>  struct make_kw_spec;  template <class K, class T>  struct make_kw_spec<K(T)>  {      typedef arg_spec<          typename keyword<K>::type        , typename required<K>::type        , typename optimized<K>::type        , T      > type;  };} // namespace auxtemplate <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>struct init   : boost::python::def_visitor<init<ParameterSpecs, CallPolicies> >{    init(CallPolicies call_policies = CallPolicies())      : call_policies(call_policies)    {}    template <class CallPolicies1>    init<ParameterSpecs, CallPolicies1>     operator[](CallPolicies1 const& call_policies) const    {        return init<ParameterSpecs, CallPolicies1>(call_policies);    }    template <class Class>    void visit_aux(Class& cl, mpl::true_) const    {        cl.def(boost::python::init<>()[call_policies]);    }    template <class Class>    void visit_aux(Class& cl, mpl::false_) const    {        typedef typename mpl::transform<            ParameterSpecs          , aux::make_kw_spec<mpl::_>          , mpl::back_inserter<mpl::vector0<> >        >::type arg_specs;        typedef typename mpl::count_if<            arg_specs          , aux::is_optional<mpl::_>        >::type optional_arity;        typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;        aux::def_combinations(            aux::def_init<Class, CallPolicies>(cl, call_policies)          , (arg_specs*)0          , mpl::long_<0>()          , mpl::long_<upper::value>()          , (aux::make_init_invoker<typename Class::wrapped_type>*)0        );    }    template <class Class>    void visit(Class& cl) const    {        visit_aux(cl, mpl::empty<ParameterSpecs>());    }    CallPolicies call_policies;};template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>struct call   : boost::python::def_visitor<call<ParameterSpecs, CallPolicies> >{    call(CallPolicies const& call_policies = CallPolicies())      : call_policies(call_policies)    {}    template <class CallPolicies1>    call<ParameterSpecs, CallPolicies1>    operator[](CallPolicies1 const& call_policies) const    {        return call<ParameterSpecs, CallPolicies1>(call_policies);    }    template <class Class>    void visit(Class& cl) const    {        typedef mpl::iterator_range<            typename mpl::next<                typename mpl::begin<ParameterSpecs>::type            >::type          , typename mpl::end<ParameterSpecs>::type        > arg_types;        typedef typename mpl::front<ParameterSpecs>::type result_type;        typedef typename mpl::transform<            arg_types          , aux::make_kw_spec<mpl::_>          , mpl::back_inserter<mpl::vector0<> >        >::type arg_specs;        typedef typename mpl::count_if<            arg_specs          , aux::is_optional<mpl::_>        >::type optional_arity;        typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;        typedef aux::call_policies_as_options<CallPolicies> options;        aux::def_combinations(            aux::def_class<Class, options>(cl, "__call__", options(call_policies))          , (arg_specs*)0          , mpl::long_<0>()          , mpl::long_<upper::value>()          , (aux::make_call_invoker<typename Class::wrapped_type, result_type>*)0        );    }    CallPolicies call_policies;};template <class Fwd, class ParameterSpecs>struct function   : boost::python::def_visitor<function<Fwd, ParameterSpecs> >{    template <class Class, class Options>    void visit(Class& cl, char const* name, Options const& options) const    {        typedef mpl::iterator_range<            typename mpl::next<                typename mpl::begin<ParameterSpecs>::type            >::type          , typename mpl::end<ParameterSpecs>::type        > arg_types;        typedef typename mpl::front<ParameterSpecs>::type result_type;        typedef typename mpl::transform<            arg_types          , aux::make_kw_spec<mpl::_>          , mpl::back_inserter<mpl::vector0<> >        >::type arg_specs;        typedef typename mpl::count_if<            arg_specs          , aux::is_optional<mpl::_>        >::type optional_arity;        typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;        aux::def_combinations(            aux::def_class<Class, Options>(cl, name, options)          , (arg_specs*)0          , mpl::long_<0>()          , mpl::long_<upper::value>()          , (aux::make_member_invoker<                Fwd, result_type, typename Class::wrapped_type            >*)0        );    }};}}} // namespace boost::parameter::python#endif // BOOST_PARAMETER_PYTHON_060209_HPP
 |