1 // Copyright David Abrahams 2002.
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 WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
6 # define WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP
8 # include <boost/python/detail/prefix.hpp>
10 # include <boost/python/default_call_policies.hpp>
11 # include <boost/python/object/life_support.hpp>
14 namespace boost
{ namespace python
{
18 template <std::size_t N
>
21 template <class ArgumentPackage
>
22 static PyObject
* execute(ArgumentPackage
const& args
, PyObject
* = 0)
24 int const pre_n
= static_cast<int>(N
) - 1; // separate line is gcc-2.96 workaround
25 return detail::get(mpl::int_
<pre_n
>(), args
);
31 template <class ArgumentPackage
>
32 static PyObject
* execute(ArgumentPackage
const&, PyObject
* zeroth
)
41 , class BasePolicy_
= default_call_policies
43 struct with_custodian_and_ward
: BasePolicy_
45 BOOST_STATIC_ASSERT(custodian
!= ward
);
46 BOOST_STATIC_ASSERT(custodian
> 0);
47 BOOST_STATIC_ASSERT(ward
> 0);
49 template <class ArgumentPackage
>
50 static bool precall(ArgumentPackage
const& args_
)
52 unsigned arity_
= detail::arity(args_
);
53 if (custodian
> arity_
|| ward
> arity_
)
57 , "boost::python::with_custodian_and_ward: argument index out of range"
62 PyObject
* patient
= detail::get_prev
<ward
>::execute(args_
);
63 PyObject
* nurse
= detail::get_prev
<custodian
>::execute(args_
);
65 PyObject
* life_support
= python::objects::make_nurse_and_patient(nurse
, patient
);
66 if (life_support
== 0)
69 bool result
= BasePolicy_::precall(args_
);
72 Py_DECREF(life_support
);
79 template <std::size_t custodian
, std::size_t ward
, class BasePolicy_
= default_call_policies
>
80 struct with_custodian_and_ward_postcall
: BasePolicy_
82 BOOST_STATIC_ASSERT(custodian
!= ward
);
84 template <class ArgumentPackage
>
85 static PyObject
* postcall(ArgumentPackage
const& args_
, PyObject
* result
)
87 std::size_t arity_
= detail::arity(args_
);
88 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
89 if ( custodian
> arity_
|| ward
> arity_
)
91 // check if either custodian or ward exceeds the arity
92 // (this weird formulation avoids "always false" warnings
94 if ( (std::max
)(custodian
, ward
) > arity_
)
99 , "boost::python::with_custodian_and_ward_postcall: argument index out of range"
104 PyObject
* patient
= detail::get_prev
<ward
>::execute(args_
, result
);
105 PyObject
* nurse
= detail::get_prev
<custodian
>::execute(args_
, result
);
107 if (nurse
== 0) return 0;
109 result
= BasePolicy_::postcall(args_
, result
);
113 if (python::objects::make_nurse_and_patient(nurse
, patient
) == 0)
123 }} // namespace boost::python
125 #endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP