1616#include < boost/mpl/at.hpp>
1717#include < boost/mpl/size.hpp>
1818#include < boost/mpl/pop_front.hpp>
19+ #include < boost/mpl/pop_back.hpp>
1920
2021#include < boost/static_assert.hpp>
2122#include < boost/preprocessor/enum_params_with_a_default.hpp>
2627#include < boost/preprocessor/dec.hpp>
2728
2829// /////////////////////////////////////////////////////////////////////////////
29- #define BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT \
30+ #define BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT \
3031 BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT \
3132 ( \
3233 BOOST_PYTHON_MAX_ARITY, \
33- typename T, \
34+ class T , \
3435 boost::mpl::null_argument \
3536 ) \
3637
37- #define BPL_IMPL_TEMPLATE_TYPES \
38+ #define BOOST_PYTHON_TEMPLATE_TYPES \
3839 BOOST_PP_ENUM_PARAMS \
3940 ( \
4041 BOOST_PYTHON_MAX_ARITY, \
41- typename T \
42+ class T \
4243 ) \
4344
44- #define BPL_IMPL_TEMPLATE_ARGS \
45+ #define BOOST_PYTHON_TEMPLATE_ARGS \
4546 BOOST_PP_ENUM_PARAMS \
4647 ( \
4748 BOOST_PYTHON_MAX_ARITY, \
5152// /////////////////////////////////////////////////////////////////////////////
5253namespace boost { namespace python {
5354
54- template <BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT >
55- struct init ;
55+ template <BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT >
56+ struct init ; // forward declaration
5657
5758// /////////////////////////////////////
58- template <BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT >
59- struct optional ;
59+ template <BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT >
60+ struct optional ; // forward declaration
6061
6162namespace detail {
6263
@@ -67,7 +68,7 @@ namespace detail {
6768 // This metaprogram checks if T is nil
6869 //
6970 // /////////////////////////////////////////////////////////////////////////
70- template <typename T>
71+ template <class T >
7172 struct is_nil : public boost ::is_same<T, boost::mpl::null_argument> {};
7273
7374 // /////////////////////////////////////////////////////////////////////////
@@ -79,13 +80,13 @@ namespace detail {
7980 // /////////////////////////////////////////////////////////////////////////
8081 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
8182
82- template <typename T>
83+ template <class T >
8384 struct is_optional {
8485
8586 private:
8687
87- template <BPL_IMPL_TEMPLATE_TYPES >
88- static boost::type_traits::yes_type f (optional<BPL_IMPL_TEMPLATE_ARGS >);
88+ template <BOOST_PYTHON_TEMPLATE_TYPES >
89+ static boost::type_traits::yes_type f (optional<BOOST_PYTHON_TEMPLATE_ARGS >);
8990 static boost::type_traits::no_type f (...);
9091 static T t ();
9192
@@ -99,14 +100,14 @@ namespace detail {
99100 // /////////////////////////////////////
100101 #else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
101102
102- template <typename T>
103+ template <class T >
103104 struct is_optional {
104105
105106 BOOST_STATIC_CONSTANT (bool , value = false );
106107 };
107108
108- template <BPL_IMPL_TEMPLATE_TYPES >
109- struct is_optional <optional<BPL_IMPL_TEMPLATE_ARGS > > {
109+ template <BOOST_PYTHON_TEMPLATE_TYPES >
110+ struct is_optional <optional<BOOST_PYTHON_TEMPLATE_ARGS > > {
110111
111112 BOOST_STATIC_CONSTANT (bool , value = true );
112113 };
@@ -227,10 +228,12 @@ namespace detail {
227228 };
228229 };
229230
230- template <BPL_IMPL_TEMPLATE_TYPES>
231- struct check_init_params {
231+ struct init_base {};
232+
233+ template <BOOST_PYTHON_TEMPLATE_TYPES>
234+ struct check_init_params : init_base {
232235
233- typedef boost::mpl::type_list<BPL_IMPL_TEMPLATE_ARGS > params;
236+ typedef boost::mpl::type_list<BOOST_PYTHON_TEMPLATE_ARGS > params;
234237
235238 BOOST_STATIC_ASSERT
236239 (
@@ -273,7 +276,7 @@ namespace detail {
273276 {
274277 };
275278
276- template <BPL_IMPL_TEMPLATE_TYPES >
279+ template <BOOST_PYTHON_TEMPLATE_TYPES >
277280 struct count_optional_types {
278281
279282 BOOST_STATIC_CONSTANT (int , value =
@@ -295,25 +298,27 @@ namespace detail {
295298// last in the list.
296299//
297300// /////////////////////////////////////////////////////////////////////////////
298- #define BPL_IMPL_APPEND_TO_INIT (INDEX, D ) \
301+ #define BOOST_PYTHON_APPEND_TO_INIT (INDEX, D ) \
299302 typedef typename detail::append_to_init \
300303 < \
301304 BOOST_PP_CAT (l, INDEX), \
302305 BOOST_PP_CAT (T, BOOST_PP_INC(INDEX)) \
303306 >::sequence BOOST_PP_CAT (l, BOOST_PP_INC(INDEX)); \
304307
305308
306- template <BPL_IMPL_TEMPLATE_TYPES >
307- struct init : detail::check_init_params<BPL_IMPL_TEMPLATE_ARGS> {
308-
309+ template <BOOST_PYTHON_TEMPLATE_TYPES >
310+ struct init : detail::check_init_params<BOOST_PYTHON_TEMPLATE_ARGS>
311+ {
309312 typedef boost::mpl::type_list<T0> l0;
310313 BOOST_PP_REPEAT
311- (BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BPL_IMPL_APPEND_TO_INIT , 0 );
314+ (BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BOOST_PYTHON_APPEND_TO_INIT , 0 );
312315
313316 typedef BOOST_PP_CAT (l, BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY)) sequence;
314317
318+ BOOST_STATIC_CONSTANT (int , n_arguments = boost::mpl::size<sequence>::value);
319+
315320 BOOST_STATIC_CONSTANT (int , n_defaults =
316- (detail::count_optional_types<BPL_IMPL_TEMPLATE_ARGS >::value)
321+ (detail::count_optional_types<BOOST_PYTHON_TEMPLATE_ARGS >::value)
317322 );
318323};
319324
@@ -324,19 +329,96 @@ struct init : detail::check_init_params<BPL_IMPL_TEMPLATE_ARGS> {
324329// optional<T0...TN>::sequence returns a typelist.
325330//
326331// /////////////////////////////////////////////////////////////////////////////
327- template <BPL_IMPL_TEMPLATE_TYPES >
332+ template <BOOST_PYTHON_TEMPLATE_TYPES >
328333struct optional {
329334
330- typedef boost::mpl::type_list<BPL_IMPL_TEMPLATE_ARGS > sequence;
335+ typedef boost::mpl::type_list<BOOST_PYTHON_TEMPLATE_ARGS > sequence;
331336};
332337
333- #undef BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT
334- #undef BPL_IMPL_TEMPLATE_TYPES
335- #undef BPL_IMPL_TEMPLATE_ARGS
336- #undef BPL_IMPL_IS_OPTIONAL_VALUE
337- #undef BPL_IMPL_APPEND_TO_INIT
338+ namespace detail {
339+
340+ // /////////////////////////////////////////////////////////////////////////////
341+ //
342+ // define_class_init_helper<N>::apply
343+ //
344+ // General case
345+ //
346+ // Accepts a class_ and an arguments list. Defines a constructor
347+ // for the class given the arguments and recursively calls
348+ // define_class_init_helper<N-1>::apply with one less arguments (the
349+ // rightmost argument is shaved off)
350+ //
351+ // /////////////////////////////////////////////////////////////////////////////
352+ template <int N>
353+ struct define_class_init_helper {
354+
355+ template <class ClassT , class ArgsT >
356+ static void apply (ClassT& cl, ArgsT const & args, char const * doc)
357+ {
358+ cl.def_init (args, default_call_policies (), doc);
359+ boost::mpl::pop_back<ArgsT>::sequence next;
360+ define_class_init_helper<N-1 >::apply (cl, next, doc);
361+ }
362+ };
363+
364+ // /////////////////////////////////////////////////////////////////////////////
365+ //
366+ // define_class_init_helper<0>::apply
367+ //
368+ // Terminal case
369+ //
370+ // Accepts a class_ and an arguments list. Defines a constructor
371+ // for the class given the arguments.
372+ //
373+ // /////////////////////////////////////////////////////////////////////////////
374+ template <>
375+ struct define_class_init_helper <0 > {
376+
377+ template <class ClassT , class ArgsT >
378+ static void apply (ClassT& cl, ArgsT const & args, char const * doc)
379+ {
380+ cl.def_init (args, default_call_policies (), doc);
381+ }
382+ };
383+ }
338384
339- }} // namespace boost { namespace python {
385+ // /////////////////////////////////////////////////////////////////////////////
386+ //
387+ // define_init
388+ //
389+ // Accepts a class_ and an init-list. Defines a set of constructors for
390+ // the class given the arguments. The init list (see init above) has
391+ // n_defaults (number of default arguments and n_arguments (number of
392+ // actual arguments). This function defines n_defaults + 1 constructors
393+ // for the class. Each constructor after the first has one less argument
394+ // to its right. Example:
395+ //
396+ // init<int, default<char, long, double>
397+ //
398+ // Defines:
399+ //
400+ // __init__(int, char, long, double)
401+ // __init__(int, char, long)
402+ // __init__(int, char)
403+ // __init__(int)
404+ //
405+ // /////////////////////////////////////////////////////////////////////////////
406+ template <class ClassT , class InitT >
407+ void
408+ define_init (ClassT& cl, InitT const & i, char const * doc)
409+ {
410+ enum { n_defaults_plus_1 = InitT::n_defaults + 1 };
411+ typedef typename InitT::sequence args_t ;
412+ detail::define_class_init_helper<n_defaults_plus_1>::apply (cl, args_t (), doc);
413+ }
414+
415+ }} // namespace boost::python
416+
417+ #undef BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT
418+ #undef BOOST_PYTHON_TEMPLATE_TYPES
419+ #undef BOOST_PYTHON_TEMPLATE_ARGS
420+ #undef BOOST_PYTHON_IS_OPTIONAL_VALUE
421+ #undef BOOST_PYTHON_APPEND_TO_INIT
340422
341423// /////////////////////////////////////////////////////////////////////////////
342424#endif // INIT_JDG20020820_HPP
0 commit comments