summaryrefslogtreecommitdiff
path: root/boost/python/make_constructor.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/python/make_constructor.hpp')
-rw-r--r--boost/python/make_constructor.hpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/boost/python/make_constructor.hpp b/boost/python/make_constructor.hpp
new file mode 100644
index 0000000000..8ae722bbe3
--- /dev/null
+++ b/boost/python/make_constructor.hpp
@@ -0,0 +1,290 @@
+// 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