From c7eae3512f0319c46ddeb78544f9c4546c49ff79 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 11 Sep 2002 08:13:18 +0000 Subject: [PATCH] Use xxx_front operations for type lists [SVN r15260] --- include/boost/python/init.hpp | 378 +++++++++++----------------------- 1 file changed, 122 insertions(+), 256 deletions(-) diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp index 1bb502a1..87a45829 100644 --- a/include/boost/python/init.hpp +++ b/include/boost/python/init.hpp @@ -13,20 +13,24 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include + +#include #include #include #include -#include -#include -#include -#include /////////////////////////////////////////////////////////////////////////////// #define BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT \ @@ -63,16 +67,6 @@ struct optional; // forward declaration namespace detail { - /////////////////////////////////////////////////////////////////////////// - // - // is_nil::value - // - // This metaprogram checks if T is nil - // - /////////////////////////////////////////////////////////////////////////// - template - struct is_nil : public boost::is_same {}; - /////////////////////////////////////////////////////////////////////////// // // is_optional::value @@ -97,227 +91,86 @@ namespace detail { BOOST_STATIC_CONSTANT( bool, value = sizeof(f(t())) == sizeof(::boost::type_traits::yes_type)); + typedef mpl::bool_c type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_optional,(T)) // needed for MSVC & Borland }; /////////////////////////////////////// #else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template - struct is_optional { + struct is_optional_impl { BOOST_STATIC_CONSTANT(bool, value = false); }; template - struct is_optional > { + struct is_optional_impl > { BOOST_STATIC_CONSTANT(bool, value = true); }; - #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - - /////////////////////////////////////////////////////////////////////////// - // - // append_to_init [ and helpers ] - // - // A metaprogram appends T to the initializer type list - // - /////////////////////////////////////////////////////////////////////////// - struct append_to_init_helper1 { - - // Case 1: default case, just push T to the back of ListT - - template - struct apply { - - typedef typename mpl::push_back::type type; - }; - }; - - struct append_to_init_helper2 { - - template - struct apply { - - // Case 2: optional case, T is an optional, append all - // the contents of the optional T into back of ListT - - typedef typename mpl::fold_backward< - typename T::type, - ListT, - mpl::push_front - >::type type; - }; - }; - - struct append_to_init_helper3 { - - // Case 3: nil case, we found a nil, do nothing - - template - struct apply { - - typedef ListT type; - }; - }; - - template - struct append_to_init { - - typedef typename mpl::if_c< - is_optional::value - , append_to_init_helper2 - , typename mpl::if_c< - is_nil::value - , append_to_init_helper3 - , append_to_init_helper1 - >::type - >::type helper; - - typedef typename helper::template apply::type type; - }; - - /////////////////////////////////////////////////////////////////////////// - // - // check_init_params [ and helpers ] - // - // Check the init template parameters. Detect illegal - // arguments such as: - // - // init, int> // BAD trailing int - // init, optional > // BAD optional used twice - // - /////////////////////////////////////////////////////////////////////////// - template - struct check_init_params_helper { - - template - struct apply { - - // case where size of sequence is not zero - - typedef typename mpl::pop_front::type rest; - - enum { - - // if first is optional then there must be no more - // elements to its right. if not then recurse and check - // the rest of the type list - - first_is_optional = - is_optional::type>::value, - size_of_rest = mpl::size::value, - rest_is_nil = (size_of_rest == 0), - is_ok = first_is_optional ? rest_is_nil : - check_init_params_helper - ::template apply::is_ok - }; - }; - }; - - template <> - struct check_init_params_helper<0> { - - // case where size of sequence is zero - - template - struct apply { - - enum { is_ok = true }; - }; - }; - - struct init_base {}; - - template - struct check_init_params : init_base { - - typedef mpl::list params; - - BOOST_STATIC_ASSERT - ( - check_init_params_helper::value> - ::template apply::is_ok - ); - }; - - /////////////////////////////////////////////////////////////////////////// - // - // count_optional_types [ and helpers ] - // - // count_optional_types::value computes the number of - // optional types (see init and optional below). For example: - // - // init >::value == 3 - // - /////////////////////////////////////////////////////////////////////////// template - struct count_optionals1 { - - BOOST_STATIC_CONSTANT(int, value = 0); - }; - - template - struct count_optionals2 { - - BOOST_STATIC_CONSTANT( - int, value = mpl::size::value + 1); - }; - - template - struct count_optionals - : mpl::if_c< - is_optional::value // if - , count_optionals2 // then - , count_optionals1 // else - >::type + struct is_optional : is_optional_impl { + typedef mpl::bool_c::value> type; + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_optional,(T)) // needed for MSVC & Borland }; - - template - struct count_optional_types { - - BOOST_STATIC_CONSTANT(int, value = - count_optionals::value + - count_optionals::value + - count_optionals::value - ); - }; + #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) } // namespace detail -/////////////////////////////////////////////////////////////////////////////// -// -// init -// -// init::type returns a typelist. One of T0..TN -// mat be an optional<...> see below. There should be only one -// optional in the input types and an optional should be the -// last in the list. -// -/////////////////////////////////////////////////////////////////////////////// -#define BOOST_PYTHON_APPEND_TO_INIT(z, INDEX, D) \ - typedef typename detail::append_to_init \ - < \ - BOOST_PP_CAT(l, INDEX), \ - BOOST_PP_CAT(T, BOOST_PP_INC(INDEX)) \ - >::type BOOST_PP_CAT(l, BOOST_PP_INC(INDEX)); \ - template -struct init : detail::check_init_params +struct init //: detail::check_init_params { - typedef mpl::list l0; - BOOST_PP_REPEAT - (BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BOOST_PYTHON_APPEND_TO_INIT, 0) + typedef mpl::list signature_; + typedef typename mpl::end::type finish; - typedef BOOST_PP_CAT(l, BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY)) type; + // Find the optional<> element, if any + typedef typename mpl::find_if< + signature_, detail::is_optional + >::type opt; - BOOST_STATIC_CONSTANT(int, n_arguments = mpl::size::value); - BOOST_STATIC_CONSTANT(int, n_defaults = - (detail::count_optional_types::value) - ); + // Check to make sure the optional<> element, if any, is the last one + typedef typename mpl::apply_if< + is_same + , mpl::identity + , mpl::next + >::type expected_finish; + BOOST_STATIC_ASSERT((is_same::value)); + + typedef typename mpl::apply_if< + is_same + , mpl::list<> + , opt + >::type optional_args; + + // Count the number of default args + BOOST_STATIC_CONSTANT(int, n_defaults = mpl::size::value); + + typedef typename mpl::iterator_range< + typename mpl::begin::type + , opt + >::type required_args; + + // Build a reverse image of all the args, including optionals + typedef typename mpl::fold< + required_args + , mpl::list<> + , mpl::push_front + >::type reversed_required; + + typedef typename mpl::fold< + optional_args + , reversed_required + , mpl::push_front + >::type reversed_args; + + // Count the maximum number of arguments + BOOST_STATIC_CONSTANT(int, n_arguments = mpl::size::value); }; /////////////////////////////////////////////////////////////////////////////// @@ -328,56 +181,69 @@ struct init : detail::check_init_params // /////////////////////////////////////////////////////////////////////////////// template -struct optional { - - typedef mpl::list type; +struct optional + : mpl::list +{ }; -namespace detail { +namespace detail +{ + template + void def_init_reversed(ClassT& cl, ReversedArgs const&, CallPoliciesT const& policies, char const* doc) + { + typedef typename mpl::fold< + ReversedArgs + , mpl::list<> + , mpl::push_front + >::type args; + + cl.def_init(args(), policies, doc); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper::apply + // + // General case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments and recursively calls + // define_class_init_helper::apply with one less arguments (the + // rightmost argument is shaved off) + // + /////////////////////////////////////////////////////////////////////////////// + template + struct define_class_init_helper { - /////////////////////////////////////////////////////////////////////////////// - // - // define_class_init_helper::apply - // - // General case - // - // Accepts a class_ and an arguments list. Defines a constructor - // for the class given the arguments and recursively calls - // define_class_init_helper::apply with one less arguments (the - // rightmost argument is shaved off) - // - /////////////////////////////////////////////////////////////////////////////// - template - struct define_class_init_helper { + template + static void apply(ClassT& cl, CallPoliciesT const& policies, ReversedArgs const& args, char const* doc) + { + def_init_reversed(cl, args, policies, doc); - template - static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc) - { - cl.def_init(args, policies, doc); - typename mpl::pop_back::type next; - define_class_init_helper::apply(cl, policies, next, doc); - } - }; + typename mpl::pop_front::type next; + define_class_init_helper::apply(cl, policies, next, doc); + } + }; - /////////////////////////////////////////////////////////////////////////////// - // - // define_class_init_helper<0>::apply - // - // Terminal case - // - // Accepts a class_ and an arguments list. Defines a constructor - // for the class given the arguments. - // - /////////////////////////////////////////////////////////////////////////////// - template <> - struct define_class_init_helper<0> { + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper<0>::apply + // + // Terminal case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments. + // + /////////////////////////////////////////////////////////////////////////////// + template <> + struct define_class_init_helper<0> { - template - static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc) - { - cl.def_init(args, policies, doc); - } - }; + template + static void apply(ClassT& cl, CallPoliciesT const& policies, ReversedArgs const& args, char const* doc) + { + def_init_reversed(cl, args, policies, doc); + } + }; } /////////////////////////////////////////////////////////////////////////////// @@ -405,8 +271,8 @@ template void define_init(ClassT& cl, InitT const& i, CallPoliciesT const& policies, char const* doc) { - typedef typename InitT::type args_t; - detail::define_class_init_helper::apply(cl, policies, args_t(), doc); + typedef typename InitT::reversed_args reversed_args; + detail::define_class_init_helper::apply(cl, policies, reversed_args(), doc); } }} // namespace boost::python