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