// 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 | |
{ | |
std::auto_ptr<U> owner(x); | |
dispatch(owner, mpl::false_()); | |
} | |
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 { | |
(new (memory) holder(x))->install(this->m_self); | |
} | |
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. | |
#if defined _MSC_VER && _MSC_VER < 1300 | |
typedef is_same< | |
typename BasePolicy_::result_converter | |
, default_result_converter | |
> same_result_converter; | |
//see above for explanation | |
BOOST_STATIC_ASSERT(same_result_converter::value) ; | |
#else | |
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) | |
); | |
#endif | |
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; | |
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 |