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