ossrv_pub/boost_apis/boost/python/make_constructor.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright David Abrahams 2001.
       
     2 // Distributed under the Boost Software License, Version 1.0. (See
       
     3 // accompanying file LICENSE_1_0.txt or copy at
       
     4 // http://www.boost.org/LICENSE_1_0.txt)
       
     5 #ifndef MAKE_CONSTRUCTOR_DWA20011221_HPP
       
     6 # define MAKE_CONSTRUCTOR_DWA20011221_HPP
       
     7 
       
     8 # include <boost/python/detail/prefix.hpp>
       
     9 
       
    10 # include <boost/python/default_call_policies.hpp>
       
    11 # include <boost/python/args.hpp>
       
    12 # include <boost/python/object_fwd.hpp>
       
    13 
       
    14 # include <boost/python/object/function_object.hpp>
       
    15 # include <boost/python/object/make_holder.hpp>
       
    16 # include <boost/python/object/pointer_holder.hpp>
       
    17 # include <boost/python/converter/context_result_converter.hpp>
       
    18 
       
    19 # include <boost/python/detail/caller.hpp>
       
    20 # include <boost/python/detail/none.hpp>
       
    21 
       
    22 # include <boost/mpl/size.hpp>
       
    23 # include <boost/mpl/int.hpp>
       
    24 # include <boost/mpl/push_front.hpp>
       
    25 # include <boost/mpl/pop_front.hpp>
       
    26 
       
    27 namespace boost { namespace python {
       
    28 
       
    29 namespace detail
       
    30 {
       
    31   template <class T>
       
    32   struct install_holder : converter::context_result_converter
       
    33   {
       
    34       install_holder(PyObject* args_)
       
    35         : m_self(PyTuple_GetItem(args_, 0)) {}
       
    36 
       
    37       PyObject* operator()(T x) const
       
    38       {
       
    39           dispatch(x, is_pointer<T>());
       
    40           return none();
       
    41       }
       
    42 
       
    43    private:
       
    44       template <class U>
       
    45       void dispatch(U* x, mpl::true_) const
       
    46       {
       
    47           std::auto_ptr<U> owner(x);
       
    48           dispatch(owner, mpl::false_());
       
    49       }
       
    50       
       
    51       template <class Ptr>
       
    52       void dispatch(Ptr x, mpl::false_) const
       
    53       {
       
    54           typedef typename pointee<Ptr>::type value_type;
       
    55           typedef objects::pointer_holder<Ptr,value_type> holder;
       
    56           typedef objects::instance<holder> instance_t;
       
    57 
       
    58           void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
       
    59           try {
       
    60               (new (memory) holder(x))->install(this->m_self);
       
    61           }
       
    62           catch(...) {
       
    63               holder::deallocate(this->m_self, memory);
       
    64               throw;
       
    65           }
       
    66       }
       
    67       
       
    68       PyObject* m_self;
       
    69   };
       
    70   
       
    71   struct constructor_result_converter
       
    72   {
       
    73       template <class T>
       
    74       struct apply
       
    75       {
       
    76           typedef install_holder<T> type;
       
    77       };
       
    78   };
       
    79 
       
    80   template <class BaseArgs, class Offset>
       
    81   struct offset_args
       
    82   {
       
    83       offset_args(BaseArgs base_) : base(base_) {}
       
    84       BaseArgs base;
       
    85   };
       
    86 
       
    87   template <int N, class BaseArgs, class Offset>
       
    88   inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
       
    89   {
       
    90       return get(mpl::int_<(N+Offset::value)>(), args_.base);
       
    91   }
       
    92   
       
    93   template <class BaseArgs, class Offset>
       
    94   inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
       
    95   {
       
    96       return arity(args_.base) - Offset::value;
       
    97   }
       
    98 
       
    99   template <class BasePolicy_ = default_call_policies>
       
   100   struct constructor_policy : BasePolicy_
       
   101   {
       
   102       constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
       
   103       
       
   104       // If the BasePolicy_ supplied a result converter it would be
       
   105       // ignored; issue an error if it's not the default.
       
   106       BOOST_STATIC_ASSERT((
       
   107           is_same<
       
   108               typename BasePolicy_::result_converter
       
   109             , default_result_converter
       
   110           >::value
       
   111       ));
       
   112       
       
   113       typedef constructor_result_converter result_converter;
       
   114       typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
       
   115   };
       
   116 
       
   117   template <class InnerSignature>
       
   118   struct outer_constructor_signature
       
   119   {
       
   120       typedef typename mpl::pop_front<InnerSignature>::type inner_args;
       
   121       typedef typename mpl::push_front<inner_args,object>::type outer_args;
       
   122       typedef typename mpl::push_front<outer_args,void>::type type;
       
   123   };
       
   124 
       
   125   // ETI workaround
       
   126   template <>
       
   127   struct outer_constructor_signature<int>
       
   128   {
       
   129       typedef int type;
       
   130   };
       
   131   
       
   132   //
       
   133   // These helper functions for make_constructor (below) do the raw work
       
   134   // of constructing a Python object from some invokable entity. See
       
   135   // <boost/python/detail/caller.hpp> for more information about how
       
   136   // the Sig arguments is used.
       
   137   //
       
   138   // @group make_constructor_aux {
       
   139   template <class F, class CallPolicies, class Sig>
       
   140   object make_constructor_aux(
       
   141       F f                             // An object that can be invoked by detail::invoke()
       
   142     , CallPolicies const& p           // CallPolicies to use in the invocation
       
   143     , Sig const&                      // An MPL sequence of argument types expected by F
       
   144   )
       
   145   {
       
   146       typedef typename outer_constructor_signature<Sig>::type outer_signature;
       
   147 
       
   148       typedef constructor_policy<CallPolicies> inner_policy;
       
   149       
       
   150       return objects::function_object(
       
   151           objects::py_function(
       
   152               detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
       
   153             , outer_signature()
       
   154           )
       
   155       );
       
   156   }
       
   157   
       
   158   // As above, except that it accepts argument keywords. NumKeywords
       
   159   // is used only for a compile-time assertion to make sure the user
       
   160   // doesn't pass more keywords than the function can accept. To
       
   161   // disable all checking, pass mpl::int_<0> for NumKeywords.
       
   162   template <class F, class CallPolicies, class Sig, class NumKeywords>
       
   163   object make_constructor_aux(
       
   164       F f
       
   165       , CallPolicies const& p
       
   166       , Sig const&
       
   167       , detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
       
   168       , NumKeywords                     // An MPL integral type wrapper: the size of kw
       
   169       )
       
   170   {
       
   171       enum { arity = mpl::size<Sig>::value - 1 };
       
   172       
       
   173       typedef typename detail::error::more_keywords_than_function_arguments<
       
   174           NumKeywords::value, arity
       
   175           >::too_many_keywords assertion;
       
   176     
       
   177       typedef typename outer_constructor_signature<Sig>::type outer_signature;
       
   178 
       
   179       typedef constructor_policy<CallPolicies> inner_policy;
       
   180       
       
   181       return objects::function_object(
       
   182           objects::py_function(
       
   183               detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
       
   184             , outer_signature()
       
   185           )
       
   186           , kw
       
   187       );
       
   188   }
       
   189   // }
       
   190 
       
   191   //
       
   192   //   These dispatch functions are used to discriminate between the
       
   193   //   cases when the 3rd argument is keywords or when it is a
       
   194   //   signature.
       
   195   //
       
   196   //   @group Helpers for make_constructor when called with 3 arguments. {
       
   197   //
       
   198   template <class F, class CallPolicies, class Keywords>
       
   199   object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
       
   200   {
       
   201       return detail::make_constructor_aux(
       
   202           f
       
   203         , policies
       
   204         , detail::get_signature(f)
       
   205         , kw.range()
       
   206         , mpl::int_<Keywords::size>()
       
   207       );
       
   208   }
       
   209 
       
   210   template <class F, class CallPolicies, class Signature>
       
   211   object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
       
   212   {
       
   213       return detail::make_constructor_aux(
       
   214           f
       
   215         , policies
       
   216         , sig
       
   217       );
       
   218   }
       
   219   // }
       
   220 }
       
   221 
       
   222 //   These overloaded functions wrap a function or member function
       
   223 //   pointer as a Python object, using optional CallPolicies,
       
   224 //   Keywords, and/or Signature. @group {
       
   225 //
       
   226 template <class F>
       
   227 object make_constructor(F f)
       
   228 {
       
   229     return detail::make_constructor_aux(
       
   230         f,default_call_policies(), detail::get_signature(f));
       
   231 }
       
   232 
       
   233 template <class F, class CallPolicies>
       
   234 object make_constructor(F f, CallPolicies const& policies)
       
   235 {
       
   236     return detail::make_constructor_aux(
       
   237         f, policies, detail::get_signature(f));
       
   238 }
       
   239 
       
   240 template <class F, class CallPolicies, class KeywordsOrSignature>
       
   241 object make_constructor(
       
   242     F f
       
   243   , CallPolicies const& policies
       
   244   , KeywordsOrSignature const& keywords_or_signature)
       
   245 {
       
   246     typedef typename
       
   247         detail::is_reference_to_keywords<KeywordsOrSignature&>::type
       
   248         is_kw;
       
   249     
       
   250     return detail::make_constructor_dispatch(
       
   251         f
       
   252       , policies
       
   253       , keywords_or_signature
       
   254       , is_kw()
       
   255     );
       
   256 }
       
   257 
       
   258 template <class F, class CallPolicies, class Keywords, class Signature>
       
   259 object make_constructor(
       
   260     F f
       
   261   , CallPolicies const& policies
       
   262   , Keywords const& kw
       
   263   , Signature const& sig
       
   264  )
       
   265 {
       
   266     return detail::make_constructor_aux(
       
   267           f
       
   268         , policies
       
   269         , sig
       
   270         , kw.range()
       
   271         , mpl::int_<Keywords::size>()
       
   272       );
       
   273 }
       
   274 // }
       
   275 
       
   276 }} 
       
   277 
       
   278 
       
   279 #endif // MAKE_CONSTRUCTOR_DWA20011221_HPP