291 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
// Copyright David Abrahams 2001.
 | 
						|
// Distributed under 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 MAKE_CONSTRUCTOR_DWA20011221_HPP
 | 
						|
# define MAKE_CONSTRUCTOR_DWA20011221_HPP
 | 
						|
 | 
						|
# include <boost/python/detail/prefix.hpp>
 | 
						|
 | 
						|
# include <boost/python/default_call_policies.hpp>
 | 
						|
# include <boost/python/args.hpp>
 | 
						|
# include <boost/python/object_fwd.hpp>
 | 
						|
 | 
						|
# include <boost/python/object/function_object.hpp>
 | 
						|
# include <boost/python/object/make_holder.hpp>
 | 
						|
# include <boost/python/object/pointer_holder.hpp>
 | 
						|
# include <boost/python/converter/context_result_converter.hpp>
 | 
						|
 | 
						|
# include <boost/python/detail/caller.hpp>
 | 
						|
# include <boost/python/detail/none.hpp>
 | 
						|
 | 
						|
# include <boost/mpl/size.hpp>
 | 
						|
# include <boost/mpl/int.hpp>
 | 
						|
# include <boost/mpl/push_front.hpp>
 | 
						|
# include <boost/mpl/pop_front.hpp>
 | 
						|
# include <boost/mpl/assert.hpp>
 | 
						|
 | 
						|
namespace boost { namespace python {
 | 
						|
 | 
						|
namespace detail
 | 
						|
{
 | 
						|
  template <class T>
 | 
						|
  struct install_holder : converter::context_result_converter
 | 
						|
  {
 | 
						|
      install_holder(PyObject* args_)
 | 
						|
        : m_self(PyTuple_GetItem(args_, 0)) {}
 | 
						|
 | 
						|
      PyObject* operator()(T x) const
 | 
						|
      {
 | 
						|
          dispatch(x, is_pointer<T>());
 | 
						|
          return none();
 | 
						|
      }
 | 
						|
 | 
						|
   private:
 | 
						|
      template <class U>
 | 
						|
      void dispatch(U* x, mpl::true_) const
 | 
						|
      {
 | 
						|
#if __cplusplus < 201103L
 | 
						|
	std::auto_ptr<U> owner(x);
 | 
						|
	dispatch(owner, mpl::false_());
 | 
						|
#else
 | 
						|
	std::unique_ptr<U> owner(x);
 | 
						|
	dispatch(std::move(owner), mpl::false_());
 | 
						|
#endif
 | 
						|
      }
 | 
						|
      
 | 
						|
      template <class Ptr>
 | 
						|
      void dispatch(Ptr x, mpl::false_) const
 | 
						|
      {
 | 
						|
          typedef typename pointee<Ptr>::type value_type;
 | 
						|
          typedef objects::pointer_holder<Ptr,value_type> holder;
 | 
						|
          typedef objects::instance<holder> instance_t;
 | 
						|
 | 
						|
          void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
 | 
						|
          try {
 | 
						|
#if __cplusplus < 201103L
 | 
						|
              (new (memory) holder(x))->install(this->m_self);
 | 
						|
#else
 | 
						|
              (new (memory) holder(std::move(x)))->install(this->m_self);
 | 
						|
#endif
 | 
						|
          }
 | 
						|
          catch(...) {
 | 
						|
              holder::deallocate(this->m_self, memory);
 | 
						|
              throw;
 | 
						|
          }
 | 
						|
      }
 | 
						|
      
 | 
						|
      PyObject* m_self;
 | 
						|
  };
 | 
						|
  
 | 
						|
  struct constructor_result_converter
 | 
						|
  {
 | 
						|
      template <class T>
 | 
						|
      struct apply
 | 
						|
      {
 | 
						|
          typedef install_holder<T> type;
 | 
						|
      };
 | 
						|
  };
 | 
						|
 | 
						|
  template <class BaseArgs, class Offset>
 | 
						|
  struct offset_args
 | 
						|
  {
 | 
						|
      offset_args(BaseArgs base_) : base(base_) {}
 | 
						|
      BaseArgs base;
 | 
						|
  };
 | 
						|
 | 
						|
  template <int N, class BaseArgs, class Offset>
 | 
						|
  inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
 | 
						|
  {
 | 
						|
      return get(mpl::int_<(N+Offset::value)>(), args_.base);
 | 
						|
  }
 | 
						|
  
 | 
						|
  template <class BaseArgs, class Offset>
 | 
						|
  inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
 | 
						|
  {
 | 
						|
      return arity(args_.base) - Offset::value;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class BasePolicy_ = default_call_policies>
 | 
						|
  struct constructor_policy : BasePolicy_
 | 
						|
  {
 | 
						|
      constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
 | 
						|
      
 | 
						|
      // If the BasePolicy_ supplied a result converter it would be
 | 
						|
      // ignored; issue an error if it's not the default.
 | 
						|
      BOOST_MPL_ASSERT_MSG(
 | 
						|
         (is_same<
 | 
						|
              typename BasePolicy_::result_converter
 | 
						|
            , default_result_converter
 | 
						|
          >::value)
 | 
						|
        , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
 | 
						|
        , (typename BasePolicy_::result_converter)
 | 
						|
      );
 | 
						|
      typedef constructor_result_converter result_converter;
 | 
						|
      typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
 | 
						|
  };
 | 
						|
 | 
						|
  template <class InnerSignature>
 | 
						|
  struct outer_constructor_signature
 | 
						|
  {
 | 
						|
      typedef typename mpl::pop_front<InnerSignature>::type inner_args;
 | 
						|
      typedef typename mpl::push_front<inner_args,object>::type outer_args;
 | 
						|
      typedef typename mpl::push_front<outer_args,void>::type type;
 | 
						|
  };
 | 
						|
 | 
						|
  // ETI workaround
 | 
						|
  template <>
 | 
						|
  struct outer_constructor_signature<int>
 | 
						|
  {
 | 
						|
      typedef int type;
 | 
						|
  };
 | 
						|
  
 | 
						|
  //
 | 
						|
  // These helper functions for make_constructor (below) do the raw work
 | 
						|
  // of constructing a Python object from some invokable entity. See
 | 
						|
  // <boost/python/detail/caller.hpp> for more information about how
 | 
						|
  // the Sig arguments is used.
 | 
						|
  //
 | 
						|
  // @group make_constructor_aux {
 | 
						|
  template <class F, class CallPolicies, class Sig>
 | 
						|
  object make_constructor_aux(
 | 
						|
      F f                             // An object that can be invoked by detail::invoke()
 | 
						|
    , CallPolicies const& p           // CallPolicies to use in the invocation
 | 
						|
    , Sig const&                      // An MPL sequence of argument types expected by F
 | 
						|
  )
 | 
						|
  {
 | 
						|
      typedef typename outer_constructor_signature<Sig>::type outer_signature;
 | 
						|
 | 
						|
      typedef constructor_policy<CallPolicies> inner_policy;
 | 
						|
      
 | 
						|
      return objects::function_object(
 | 
						|
          objects::py_function(
 | 
						|
              detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
 | 
						|
            , outer_signature()
 | 
						|
          )
 | 
						|
      );
 | 
						|
  }
 | 
						|
  
 | 
						|
  // As above, except that it accepts argument keywords. NumKeywords
 | 
						|
  // is used only for a compile-time assertion to make sure the user
 | 
						|
  // doesn't pass more keywords than the function can accept. To
 | 
						|
  // disable all checking, pass mpl::int_<0> for NumKeywords.
 | 
						|
  template <class F, class CallPolicies, class Sig, class NumKeywords>
 | 
						|
  object make_constructor_aux(
 | 
						|
      F f
 | 
						|
      , CallPolicies const& p
 | 
						|
      , Sig const&
 | 
						|
      , detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
 | 
						|
      , NumKeywords                     // An MPL integral type wrapper: the size of kw
 | 
						|
      )
 | 
						|
  {
 | 
						|
      enum { arity = mpl::size<Sig>::value - 1 };
 | 
						|
      
 | 
						|
      typedef typename detail::error::more_keywords_than_function_arguments<
 | 
						|
          NumKeywords::value, arity
 | 
						|
          >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
 | 
						|
    
 | 
						|
      typedef typename outer_constructor_signature<Sig>::type outer_signature;
 | 
						|
 | 
						|
      typedef constructor_policy<CallPolicies> inner_policy;
 | 
						|
      
 | 
						|
      return objects::function_object(
 | 
						|
          objects::py_function(
 | 
						|
              detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
 | 
						|
            , outer_signature()
 | 
						|
          )
 | 
						|
          , kw
 | 
						|
      );
 | 
						|
  }
 | 
						|
  // }
 | 
						|
 | 
						|
  //
 | 
						|
  //   These dispatch functions are used to discriminate between the
 | 
						|
  //   cases when the 3rd argument is keywords or when it is a
 | 
						|
  //   signature.
 | 
						|
  //
 | 
						|
  //   @group Helpers for make_constructor when called with 3 arguments. {
 | 
						|
  //
 | 
						|
  template <class F, class CallPolicies, class Keywords>
 | 
						|
  object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
 | 
						|
  {
 | 
						|
      return detail::make_constructor_aux(
 | 
						|
          f
 | 
						|
        , policies
 | 
						|
        , detail::get_signature(f)
 | 
						|
        , kw.range()
 | 
						|
        , mpl::int_<Keywords::size>()
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  template <class F, class CallPolicies, class Signature>
 | 
						|
  object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
 | 
						|
  {
 | 
						|
      return detail::make_constructor_aux(
 | 
						|
          f
 | 
						|
        , policies
 | 
						|
        , sig
 | 
						|
      );
 | 
						|
  }
 | 
						|
  // }
 | 
						|
}
 | 
						|
 | 
						|
//   These overloaded functions wrap a function or member function
 | 
						|
//   pointer as a Python object, using optional CallPolicies,
 | 
						|
//   Keywords, and/or Signature. @group {
 | 
						|
//
 | 
						|
template <class F>
 | 
						|
object make_constructor(F f)
 | 
						|
{
 | 
						|
    return detail::make_constructor_aux(
 | 
						|
        f,default_call_policies(), detail::get_signature(f));
 | 
						|
}
 | 
						|
 | 
						|
template <class F, class CallPolicies>
 | 
						|
object make_constructor(F f, CallPolicies const& policies)
 | 
						|
{
 | 
						|
    return detail::make_constructor_aux(
 | 
						|
        f, policies, detail::get_signature(f));
 | 
						|
}
 | 
						|
 | 
						|
template <class F, class CallPolicies, class KeywordsOrSignature>
 | 
						|
object make_constructor(
 | 
						|
    F f
 | 
						|
  , CallPolicies const& policies
 | 
						|
  , KeywordsOrSignature const& keywords_or_signature)
 | 
						|
{
 | 
						|
    typedef typename
 | 
						|
        detail::is_reference_to_keywords<KeywordsOrSignature&>::type
 | 
						|
        is_kw;
 | 
						|
    
 | 
						|
    return detail::make_constructor_dispatch(
 | 
						|
        f
 | 
						|
      , policies
 | 
						|
      , keywords_or_signature
 | 
						|
      , is_kw()
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
template <class F, class CallPolicies, class Keywords, class Signature>
 | 
						|
object make_constructor(
 | 
						|
    F f
 | 
						|
  , CallPolicies const& policies
 | 
						|
  , Keywords const& kw
 | 
						|
  , Signature const& sig
 | 
						|
 )
 | 
						|
{
 | 
						|
    return detail::make_constructor_aux(
 | 
						|
          f
 | 
						|
        , policies
 | 
						|
        , sig
 | 
						|
        , kw.range()
 | 
						|
        , mpl::int_<Keywords::size>()
 | 
						|
      );
 | 
						|
}
 | 
						|
// }
 | 
						|
 | 
						|
}} 
 | 
						|
 | 
						|
 | 
						|
#endif // MAKE_CONSTRUCTOR_DWA20011221_HPP
 |