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 // check if either custodian or ward exceeds the arity
89 // (this weird formulation avoids "always false" warnings
91 if ( (std::max)(custodian, ward) > arity_ )
95 , "boost::python::with_custodian_and_ward_postcall: argument index out of range"
100 PyObject* patient = detail::get_prev<ward>::execute(args_, result);
101 PyObject* nurse = detail::get_prev<custodian>::execute(args_, result);
103 if (nurse == 0) return 0;
105 result = BasePolicy_::postcall(args_, result);
109 if (python::objects::make_nurse_and_patient(nurse, patient) == 0)
119 }} // namespace boost::python
121 #endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP