123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- // 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, detail::true_) const
- {
- #if defined(BOOST_NO_CXX11_SMART_PTR)
- std::auto_ptr<U> owner(x);
- dispatch(owner, detail::false_());
- #else
- std::unique_ptr<U> owner(x);
- dispatch(std::move(owner), detail::false_());
- #endif
- }
-
- template <class Ptr>
- void dispatch(Ptr x, detail::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 defined(BOOST_NO_CXX11_SMART_PTR)
- (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
|