1 // Copyright David Abrahams and Nikolay Mladenov 2003. 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 RETURN_ARG_DWA2003719_HPP 6 # define RETURN_ARG_DWA2003719_HPP 7 # include <boost/python/default_call_policies.hpp> 8 # include <boost/python/detail/none.hpp> 9 # include <boost/python/detail/value_arg.hpp> 10 11 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES 12 # include <boost/python/converter/pytype_function.hpp> 13 #endif 14 15 # include <boost/type_traits/add_reference.hpp> 16 # include <boost/type_traits/add_const.hpp> 17 18 # include <boost/mpl/int.hpp> 19 # include <boost/mpl/at.hpp> 20 21 # include <boost/static_assert.hpp> 22 # include <boost/python/refcount.hpp> 23 24 # include <cstddef> 25 26 namespace boost { namespace python { 27 28 namespace detail 29 { 30 template <std::size_t> 31 struct return_arg_pos_argument_must_be_positive 32 # if defined(__GNUC__) || defined(__EDG__) 33 {} 34 # endif 35 ; 36 37 struct return_none 38 { 39 template <class T> struct apply 40 { 41 struct type 42 { convertibleboost::python::detail::return_none::apply::type43 static bool convertible() 44 { 45 return true; 46 } 47 operator ()boost::python::detail::return_none::apply::type48 PyObject *operator()( typename value_arg<T>::type ) const 49 { 50 return none(); 51 } 52 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES get_pytypeboost::python::detail::return_none::apply::type53 PyTypeObject const *get_pytype() const { return converter::expected_pytype_for_arg<T>::get_pytype() ; } 54 #endif 55 }; 56 }; 57 }; 58 } 59 60 template < 61 std::size_t arg_pos=1 62 , class Base = default_call_policies 63 > 64 struct return_arg : Base 65 { 66 private: 67 BOOST_STATIC_CONSTANT(bool, legal = arg_pos > 0); 68 69 public: 70 typedef typename mpl::if_c< 71 legal 72 , detail::return_none 73 , detail::return_arg_pos_argument_must_be_positive<arg_pos> 74 // we could default to the base result_converter in case or 75 // arg_pos==0 since return arg 0 means return result, but I 76 // think it is better to issue an error instead, cause it can 77 // lead to confusions 78 >::type result_converter; 79 80 template <class ArgumentPackage> postcallboost::python::return_arg81 static PyObject* postcall(ArgumentPackage const& args, PyObject* result) 82 { 83 // In case of arg_pos == 0 we could simply return Base::postcall, 84 // but this is redundant 85 BOOST_STATIC_ASSERT(arg_pos > 0); 86 87 result = Base::postcall(args,result); 88 if (!result) 89 return 0; 90 Py_DECREF(result); 91 return incref( detail::get(mpl::int_<arg_pos-1>(),args) ); 92 } 93 94 template <class Sig> 95 struct extract_return_type : mpl::at_c<Sig, arg_pos> 96 { 97 }; 98 99 }; 100 101 template < 102 class Base = default_call_policies 103 > 104 struct return_self 105 : return_arg<1,Base> 106 {}; 107 108 }} // namespace boost::python 109 110 #endif // RETURN_ARG_DWA2003719_HPP 111