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
8 # include <boost/python/detail/prefix.hpp>
10 # include <boost/python/default_call_policies.hpp>
11 # include <boost/python/args.hpp>
12 # include <boost/python/object_fwd.hpp>
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>
19 # include <boost/python/detail/caller.hpp>
20 # include <boost/python/detail/none.hpp>
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 # include <boost/mpl/assert.hpp>
28 namespace boost
{ namespace python
{
33 struct install_holder
: converter::context_result_converter
35 install_holder(PyObject
* args_
)
36 : m_self(PyTuple_GetItem(args_
, 0)) {}
38 PyObject
* operator()(T x
) const
40 dispatch(x
, is_pointer
<T
>());
46 void dispatch(U
* x
, mpl::true_
) const
48 std::auto_ptr
<U
> owner(x
);
49 dispatch(owner
, mpl::false_());
53 void dispatch(Ptr x
, mpl::false_
) const
55 typedef typename pointee
<Ptr
>::type value_type
;
56 typedef objects::pointer_holder
<Ptr
,value_type
> holder
;
57 typedef objects::instance
<holder
> instance_t
;
59 void* memory
= holder::allocate(this->m_self
, offsetof(instance_t
, storage
), sizeof(holder
));
61 (new (memory
) holder(x
))->install(this->m_self
);
64 holder::deallocate(this->m_self
, memory
);
72 struct constructor_result_converter
77 typedef install_holder
<T
> type
;
81 template <class BaseArgs
, class Offset
>
84 offset_args(BaseArgs base_
) : base(base_
) {}
88 template <int N
, class BaseArgs
, class Offset
>
89 inline PyObject
* get(mpl::int_
<N
>, offset_args
<BaseArgs
,Offset
> const& args_
)
91 return get(mpl::int_
<(N
+Offset::value
)>(), args_
.base
);
94 template <class BaseArgs
, class Offset
>
95 inline unsigned arity(offset_args
<BaseArgs
,Offset
> const& args_
)
97 return arity(args_
.base
) - Offset::value
;
100 template <class BasePolicy_
= default_call_policies
>
101 struct constructor_policy
: BasePolicy_
103 constructor_policy(BasePolicy_ base
) : BasePolicy_(base
) {}
105 // If the BasePolicy_ supplied a result converter it would be
106 // ignored; issue an error if it's not the default.
107 #if defined _MSC_VER && _MSC_VER < 1300
109 typename
BasePolicy_::result_converter
110 , default_result_converter
111 > same_result_converter
;
112 //see above for explanation
113 BOOST_STATIC_ASSERT(same_result_converter::value
) ;
115 BOOST_MPL_ASSERT_MSG(
117 typename
BasePolicy_::result_converter
118 , default_result_converter
120 , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
121 , (typename
BasePolicy_::result_converter
)
124 typedef constructor_result_converter result_converter
;
125 typedef offset_args
<typename
BasePolicy_::argument_package
, mpl::int_
<1> > argument_package
;
128 template <class InnerSignature
>
129 struct outer_constructor_signature
131 typedef typename
mpl::pop_front
<InnerSignature
>::type inner_args
;
132 typedef typename
mpl::push_front
<inner_args
,object
>::type outer_args
;
133 typedef typename
mpl::push_front
<outer_args
,void>::type type
;
138 struct outer_constructor_signature
<int>
144 // These helper functions for make_constructor (below) do the raw work
145 // of constructing a Python object from some invokable entity. See
146 // <boost/python/detail/caller.hpp> for more information about how
147 // the Sig arguments is used.
149 // @group make_constructor_aux {
150 template <class F
, class CallPolicies
, class Sig
>
151 object
make_constructor_aux(
152 F f
// An object that can be invoked by detail::invoke()
153 , CallPolicies
const& p
// CallPolicies to use in the invocation
154 , Sig
const& // An MPL sequence of argument types expected by F
157 typedef typename outer_constructor_signature
<Sig
>::type outer_signature
;
159 typedef constructor_policy
<CallPolicies
> inner_policy
;
161 return objects::function_object(
162 objects::py_function(
163 detail::caller
<F
,inner_policy
,Sig
>(f
, inner_policy(p
))
169 // As above, except that it accepts argument keywords. NumKeywords
170 // is used only for a compile-time assertion to make sure the user
171 // doesn't pass more keywords than the function can accept. To
172 // disable all checking, pass mpl::int_<0> for NumKeywords.
173 template <class F
, class CallPolicies
, class Sig
, class NumKeywords
>
174 object
make_constructor_aux(
176 , CallPolicies
const& p
178 , detail::keyword_range
const& kw
// a [begin,end) pair of iterators over keyword names
179 , NumKeywords
// An MPL integral type wrapper: the size of kw
182 enum { arity
= mpl::size
<Sig
>::value
- 1 };
184 typedef typename
detail::error::more_keywords_than_function_arguments
<
185 NumKeywords::value
, arity
186 >::too_many_keywords assertion
;
188 typedef typename outer_constructor_signature
<Sig
>::type outer_signature
;
190 typedef constructor_policy
<CallPolicies
> inner_policy
;
192 return objects::function_object(
193 objects::py_function(
194 detail::caller
<F
,inner_policy
,Sig
>(f
, inner_policy(p
))
203 // These dispatch functions are used to discriminate between the
204 // cases when the 3rd argument is keywords or when it is a
207 // @group Helpers for make_constructor when called with 3 arguments. {
209 template <class F
, class CallPolicies
, class Keywords
>
210 object
make_constructor_dispatch(F f
, CallPolicies
const& policies
, Keywords
const& kw
, mpl::true_
)
212 return detail::make_constructor_aux(
215 , detail::get_signature(f
)
217 , mpl::int_
<Keywords::size
>()
221 template <class F
, class CallPolicies
, class Signature
>
222 object
make_constructor_dispatch(F f
, CallPolicies
const& policies
, Signature
const& sig
, mpl::false_
)
224 return detail::make_constructor_aux(
233 // These overloaded functions wrap a function or member function
234 // pointer as a Python object, using optional CallPolicies,
235 // Keywords, and/or Signature. @group {
238 object
make_constructor(F f
)
240 return detail::make_constructor_aux(
241 f
,default_call_policies(), detail::get_signature(f
));
244 template <class F
, class CallPolicies
>
245 object
make_constructor(F f
, CallPolicies
const& policies
)
247 return detail::make_constructor_aux(
248 f
, policies
, detail::get_signature(f
));
251 template <class F
, class CallPolicies
, class KeywordsOrSignature
>
252 object
make_constructor(
254 , CallPolicies
const& policies
255 , KeywordsOrSignature
const& keywords_or_signature
)
258 detail::is_reference_to_keywords
<KeywordsOrSignature
&>::type
261 return detail::make_constructor_dispatch(
264 , keywords_or_signature
269 template <class F
, class CallPolicies
, class Keywords
, class Signature
>
270 object
make_constructor(
272 , CallPolicies
const& policies
274 , Signature
const& sig
277 return detail::make_constructor_aux(
282 , mpl::int_
<Keywords::size
>()
290 #endif // MAKE_CONSTRUCTOR_DWA20011221_HPP