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