1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright David Abrahams 2002, Joel de Guzman, 2002. 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 /////////////////////////////////////////////////////////////////////////////// 9 #ifndef DEFAULTS_GEN_JDG20020807_HPP 10 #define DEFAULTS_GEN_JDG20020807_HPP 11 12 #include <boost/python/detail/preprocessor.hpp> 13 #include <boost/preprocessor/repeat.hpp> 14 #include <boost/preprocessor/repeat_from_to.hpp> 15 #include <boost/preprocessor/enum.hpp> 16 #include <boost/preprocessor/enum_params.hpp> 17 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 18 #include <boost/preprocessor/tuple.hpp> 19 #include <boost/preprocessor/cat.hpp> 20 #include <boost/preprocessor/arithmetic/sub.hpp> 21 #include <boost/preprocessor/stringize.hpp> 22 #include <boost/preprocessor/inc.hpp> 23 #include <boost/preprocessor/empty.hpp> 24 #include <boost/preprocessor/comma_if.hpp> 25 #include <boost/config.hpp> 26 #include <boost/mpl/begin_end.hpp> 27 #include <boost/mpl/next.hpp> 28 #include <boost/mpl/deref.hpp> 29 #include <cstddef> 30 31 namespace boost { namespace python { 32 33 namespace detail 34 { 35 // overloads_base is used as a base class for all function 36 // stubs. This class holds the doc_string of the stubs. 37 struct overloads_base 38 { overloads_baseboost::python::detail::overloads_base39 overloads_base(char const* doc_) 40 : m_doc(doc_) {} 41 overloads_baseboost::python::detail::overloads_base42 overloads_base(char const* doc_, detail::keyword_range const& kw) 43 : m_doc(doc_), m_keywords(kw) {} 44 doc_stringboost::python::detail::overloads_base45 char const* doc_string() const 46 { 47 return m_doc; 48 } 49 keywordsboost::python::detail::overloads_base50 detail::keyword_range const& keywords() const 51 { 52 return m_keywords; 53 } 54 55 private: 56 char const* m_doc; 57 detail::keyword_range m_keywords; 58 }; 59 60 // overloads_proxy is generated by the overloads_common operator[] (see 61 // below). This class holds a user defined call policies of the stubs. 62 template <class CallPoliciesT, class OverloadsT> 63 struct overloads_proxy 64 : public overloads_base 65 { 66 typedef typename OverloadsT::non_void_return_type non_void_return_type; 67 typedef typename OverloadsT::void_return_type void_return_type; 68 overloads_proxyboost::python::detail::overloads_proxy69 overloads_proxy( 70 CallPoliciesT const& policies_ 71 , char const* doc 72 , keyword_range const& kw 73 ) 74 : overloads_base(doc, kw) 75 , policies(policies_) 76 {} 77 78 CallPoliciesT call_policiesboost::python::detail::overloads_proxy79 call_policies() const 80 { 81 return policies; 82 } 83 84 CallPoliciesT policies; 85 }; 86 87 // overloads_common is our default function stubs base class. This 88 // class returns the default_call_policies in its call_policies() 89 // member function. It can generate a overloads_proxy however through 90 // its operator[] 91 template <class DerivedT> 92 struct overloads_common 93 : public overloads_base 94 { overloads_commonboost::python::detail::overloads_common95 overloads_common(char const* doc) 96 : overloads_base(doc) {} 97 overloads_commonboost::python::detail::overloads_common98 overloads_common(char const* doc, keyword_range const& kw) 99 : overloads_base(doc, kw) {} 100 101 default_call_policies call_policiesboost::python::detail::overloads_common102 call_policies() const 103 { 104 return default_call_policies(); 105 } 106 107 template <class CallPoliciesT> 108 overloads_proxy<CallPoliciesT, DerivedT> operator []boost::python::detail::overloads_common109 operator[](CallPoliciesT const& policies) const 110 { 111 return overloads_proxy<CallPoliciesT, DerivedT>( 112 policies, this->doc_string(), this->keywords()); 113 } 114 }; 115 116 }}} // namespace boost::python::detail 117 118 119 #define BOOST_PYTHON_TYPEDEF_GEN(z, index, data) \ 120 typedef typename ::boost::mpl::next<BOOST_PP_CAT(iter, index)>::type \ 121 BOOST_PP_CAT(iter, BOOST_PP_INC(index)); \ 122 typedef typename ::boost::mpl::deref<BOOST_PP_CAT(iter, index)>::type \ 123 BOOST_PP_CAT(T, index); 124 125 #define BOOST_PYTHON_FUNC_WRAPPER_GEN(z, index, data) \ 126 static RT BOOST_PP_CAT(func_, \ 127 BOOST_PP_SUB_D(1, index, BOOST_PP_TUPLE_ELEM(3, 1, data))) ( \ 128 BOOST_PP_ENUM_BINARY_PARAMS_Z( \ 129 1, index, T, arg)) \ 130 { \ 131 BOOST_PP_TUPLE_ELEM(3, 2, data) \ 132 BOOST_PP_TUPLE_ELEM(3, 0, data)( \ 133 BOOST_PP_ENUM_PARAMS( \ 134 index, \ 135 arg)); \ 136 } 137 138 #define BOOST_PYTHON_GEN_FUNCTION(fname, fstubs_name, n_args, n_dflts, ret) \ 139 struct fstubs_name \ 140 { \ 141 BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(n_dflts)); \ 142 BOOST_STATIC_CONSTANT(int, max_args = n_funcs); \ 143 \ 144 template <typename SigT> \ 145 struct gen \ 146 { \ 147 typedef typename ::boost::mpl::begin<SigT>::type rt_iter; \ 148 typedef typename ::boost::mpl::deref<rt_iter>::type RT; \ 149 typedef typename ::boost::mpl::next<rt_iter>::type iter0; \ 150 \ 151 BOOST_PP_REPEAT_2ND( \ 152 n_args, \ 153 BOOST_PYTHON_TYPEDEF_GEN, \ 154 0) \ 155 \ 156 BOOST_PP_REPEAT_FROM_TO_2( \ 157 BOOST_PP_SUB_D(1, n_args, n_dflts), \ 158 BOOST_PP_INC(n_args), \ 159 BOOST_PYTHON_FUNC_WRAPPER_GEN, \ 160 (fname, BOOST_PP_SUB_D(1, n_args, n_dflts), ret)) \ 161 }; \ 162 }; \ 163 164 /////////////////////////////////////////////////////////////////////////////// 165 #define BOOST_PYTHON_MEM_FUNC_WRAPPER_GEN(z, index, data) \ 166 static RT BOOST_PP_CAT(func_, \ 167 BOOST_PP_SUB_D(1, index, BOOST_PP_TUPLE_ELEM(3, 1, data))) ( \ 168 ClassT obj BOOST_PP_COMMA_IF(index) \ 169 BOOST_PP_ENUM_BINARY_PARAMS_Z(1, index, T, arg) \ 170 ) \ 171 { \ 172 BOOST_PP_TUPLE_ELEM(3, 2, data) obj.BOOST_PP_TUPLE_ELEM(3, 0, data)( \ 173 BOOST_PP_ENUM_PARAMS(index, arg) \ 174 ); \ 175 } 176 177 #define BOOST_PYTHON_GEN_MEM_FUNCTION(fname, fstubs_name, n_args, n_dflts, ret) \ 178 struct fstubs_name \ 179 { \ 180 BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(n_dflts)); \ 181 BOOST_STATIC_CONSTANT(int, max_args = n_funcs + 1); \ 182 \ 183 template <typename SigT> \ 184 struct gen \ 185 { \ 186 typedef typename ::boost::mpl::begin<SigT>::type rt_iter; \ 187 typedef typename ::boost::mpl::deref<rt_iter>::type RT; \ 188 \ 189 typedef typename ::boost::mpl::next<rt_iter>::type class_iter; \ 190 typedef typename ::boost::mpl::deref<class_iter>::type ClassT; \ 191 typedef typename ::boost::mpl::next<class_iter>::type iter0; \ 192 \ 193 BOOST_PP_REPEAT_2ND( \ 194 n_args, \ 195 BOOST_PYTHON_TYPEDEF_GEN, \ 196 0) \ 197 \ 198 BOOST_PP_REPEAT_FROM_TO_2( \ 199 BOOST_PP_SUB_D(1, n_args, n_dflts), \ 200 BOOST_PP_INC(n_args), \ 201 BOOST_PYTHON_MEM_FUNC_WRAPPER_GEN, \ 202 (fname, BOOST_PP_SUB_D(1, n_args, n_dflts), ret)) \ 203 }; \ 204 }; 205 206 #define BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ 207 fstubs_name(char const* doc = 0) \ 208 : ::boost::python::detail::overloads_common<fstubs_name>(doc) {} \ 209 template <std::size_t N> \ 210 fstubs_name(char const* doc, ::boost::python::detail::keywords<N> const& keywords) \ 211 : ::boost::python::detail::overloads_common<fstubs_name>( \ 212 doc, keywords.range()) \ 213 { \ 214 typedef typename ::boost::python::detail:: \ 215 error::more_keywords_than_function_arguments< \ 216 N,n_args>::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED; \ 217 } \ 218 template <std::size_t N> \ 219 fstubs_name(::boost::python::detail::keywords<N> const& keywords, char const* doc = 0) \ 220 : ::boost::python::detail::overloads_common<fstubs_name>( \ 221 doc, keywords.range()) \ 222 { \ 223 typedef typename ::boost::python::detail:: \ 224 error::more_keywords_than_function_arguments< \ 225 N,n_args>::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED; \ 226 } 227 228 # if defined(BOOST_NO_VOID_RETURNS) 229 230 # define BOOST_PYTHON_GEN_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ 231 struct fstubs_name \ 232 : public ::boost::python::detail::overloads_common<fstubs_name> \ 233 { \ 234 BOOST_PYTHON_GEN_FUNCTION( \ 235 fname, non_void_return_type, n_args, n_dflts, return) \ 236 BOOST_PYTHON_GEN_FUNCTION( \ 237 fname, void_return_type, n_args, n_dflts, ;) \ 238 \ 239 BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ 240 }; 241 242 # define BOOST_PYTHON_GEN_MEM_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ 243 struct fstubs_name \ 244 : public ::boost::python::detail::overloads_common<fstubs_name> \ 245 { \ 246 BOOST_PYTHON_GEN_MEM_FUNCTION( \ 247 fname, non_void_return_type, n_args, n_dflts, return) \ 248 BOOST_PYTHON_GEN_MEM_FUNCTION( \ 249 fname, void_return_type, n_args, n_dflts, ;) \ 250 \ 251 BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \ 252 }; 253 254 # else // !defined(BOOST_NO_VOID_RETURNS) 255 256 # define BOOST_PYTHON_GEN_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ 257 struct fstubs_name \ 258 : public ::boost::python::detail::overloads_common<fstubs_name> \ 259 { \ 260 BOOST_PYTHON_GEN_FUNCTION( \ 261 fname, non_void_return_type, n_args, n_dflts, return) \ 262 \ 263 typedef non_void_return_type void_return_type; \ 264 BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ 265 }; 266 267 268 # define BOOST_PYTHON_GEN_MEM_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ 269 struct fstubs_name \ 270 : public ::boost::python::detail::overloads_common<fstubs_name> \ 271 { \ 272 BOOST_PYTHON_GEN_MEM_FUNCTION( \ 273 fname, non_void_return_type, n_args, n_dflts, return) \ 274 \ 275 typedef non_void_return_type void_return_type; \ 276 BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \ 277 }; 278 279 # endif // !defined(BOOST_NO_VOID_RETURNS) 280 281 /////////////////////////////////////////////////////////////////////////////// 282 // 283 // MAIN MACROS 284 // 285 // Given generator_name, fname, min_args and max_args, These macros 286 // generate function stubs that forward to a function or member function 287 // named fname. max_args is the arity of the function or member function 288 // fname. fname can have default arguments. min_args is the minimum 289 // arity that fname can accept. 290 // 291 // There are two versions: 292 // 293 // 1. BOOST_PYTHON_FUNCTION_OVERLOADS for free functions 294 // 2. BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS for member functions. 295 // 296 // For instance, given a function: 297 // 298 // int 299 // foo(int a, char b = 1, unsigned c = 2, double d = 3) 300 // { 301 // return a + b + c + int(d); 302 // } 303 // 304 // The macro invocation: 305 // 306 // BOOST_PYTHON_FUNCTION_OVERLOADS(foo_stubs, foo, 1, 4) 307 // 308 // Generates this code: 309 // 310 // struct foo_stubsNonVoid 311 // { 312 // static const int n_funcs = 4; 313 // static const int max_args = n_funcs; 314 // 315 // template <typename SigT> 316 // struct gen 317 // { 318 // typedef typename ::boost::mpl::begin<SigT>::type rt_iter; 319 // typedef typename rt_iter::type RT; 320 // typedef typename rt_iter::next iter0; 321 // typedef typename iter0::type T0; 322 // typedef typename iter0::next iter1; 323 // typedef typename iter1::type T1; 324 // typedef typename iter1::next iter2; 325 // typedef typename iter2::type T2; 326 // typedef typename iter2::next iter3; 327 // typedef typename iter3::type T3; 328 // typedef typename iter3::next iter4; 329 // 330 // static RT func_0(T0 arg0) 331 // { return foo(arg0); } 332 // 333 // static RT func_1(T0 arg0, T1 arg1) 334 // { return foo(arg0, arg1); } 335 // 336 // static RT func_2(T0 arg0, T1 arg1, T2 arg2) 337 // { return foo(arg0, arg1, arg2); } 338 // 339 // static RT func_3(T0 arg0, T1 arg1, T2 arg2, T3 arg3) 340 // { return foo(arg0, arg1, arg2, arg3); } 341 // }; 342 // }; 343 // 344 // struct foo_overloads 345 // : public boost::python::detail::overloads_common<foo_overloads> 346 // { 347 // typedef foo_overloadsNonVoid non_void_return_type; 348 // typedef foo_overloadsNonVoid void_return_type; 349 // 350 // foo_overloads(char const* doc = 0) 351 // : boost::python::detail::overloads_common<foo_overloads>(doc) {} 352 // }; 353 // 354 // The typedefs non_void_return_type and void_return_type are 355 // used to handle compilers that do not support void returns. The 356 // example above typedefs non_void_return_type and 357 // void_return_type to foo_overloadsNonVoid. On compilers that do 358 // not support void returns, there are two versions: 359 // foo_overloadsNonVoid and foo_overloadsVoid. The "Void" 360 // version is almost identical to the "NonVoid" version except 361 // for the return type (void) and the lack of the return keyword. 362 // 363 // See the overloads_common above for a description of the 364 // foo_overloads' base class. 365 // 366 /////////////////////////////////////////////////////////////////////////////// 367 #define BOOST_PYTHON_FUNCTION_OVERLOADS(generator_name, fname, min_args, max_args) \ 368 BOOST_PYTHON_GEN_FUNCTION_STUB( \ 369 fname, \ 370 generator_name, \ 371 max_args, \ 372 BOOST_PP_SUB_D(1, max_args, min_args)) 373 374 #define BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(generator_name, fname, min_args, max_args) \ 375 BOOST_PYTHON_GEN_MEM_FUNCTION_STUB( \ 376 fname, \ 377 generator_name, \ 378 max_args, \ 379 BOOST_PP_SUB_D(1, max_args, min_args)) 380 381 // deprecated macro names (to be removed) 382 #define BOOST_PYTHON_FUNCTION_GENERATOR BOOST_PYTHON_FUNCTION_OVERLOADS 383 #define BOOST_PYTHON_MEM_FUN_GENERATOR BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS 384 385 /////////////////////////////////////////////////////////////////////////////// 386 #endif // DEFAULTS_GEN_JDG20020807_HPP 387 388 389