os/ossrv/ossrv_pub/boost_apis/boost/python/init.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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