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;                                     \
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;                                     \
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