2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-23 05:42:30 +00:00

Use xxx_front operations for type lists

[SVN r15260]
This commit is contained in:
Dave Abrahams
2002-09-11 08:13:18 +00:00
parent 163bb06a43
commit c7eae3512f

View File

@@ -13,20 +13,24 @@
#include <boost/mpl/list.hpp>
#include <boost/mpl/fold_backward.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/iterator_range.hpp>
#include <boost/mpl/logical/not.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/enum_params_with_a_default.hpp>
#include <boost/preprocessor/enum_params.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/dec.hpp>
///////////////////////////////////////////////////////////////////////////////
#define BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT \
@@ -63,16 +67,6 @@ struct optional; // forward declaration
namespace detail {
///////////////////////////////////////////////////////////////////////////
//
// is_nil<T>::value
//
// This metaprogram checks if T is nil
//
///////////////////////////////////////////////////////////////////////////
template <class T>
struct is_nil : public boost::is_same<T, mpl::void_> {};
///////////////////////////////////////////////////////////////////////////
//
// is_optional<T>::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<value> type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_optional,(T)) // needed for MSVC & Borland
};
///////////////////////////////////////
#else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <class T>
struct is_optional {
struct is_optional_impl {
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct is_optional<optional<BOOST_PYTHON_TEMPLATE_ARGS> > {
struct is_optional_impl<optional<BOOST_PYTHON_TEMPLATE_ARGS> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
#endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
///////////////////////////////////////////////////////////////////////////
//
// append_to_init<ListT, T> [ 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 <class ListT, class T>
struct apply {
typedef typename mpl::push_back<ListT, T>::type type;
};
};
struct append_to_init_helper2 {
template <class ListT, class T>
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<mpl::_1, mpl::_2>
>::type type;
};
};
struct append_to_init_helper3 {
// Case 3: nil case, we found a nil, do nothing
template <class ListT, class T>
struct apply {
typedef ListT type;
};
};
template <class ListT, class T>
struct append_to_init {
typedef typename mpl::if_c<
is_optional<T>::value
, append_to_init_helper2
, typename mpl::if_c<
is_nil<T>::value
, append_to_init_helper3
, append_to_init_helper1
>::type
>::type helper;
typedef typename helper::template apply<ListT, T>::type type;
};
///////////////////////////////////////////////////////////////////////////
//
// check_init_params [ and helpers ]
//
// Check the init template parameters. Detect illegal
// arguments such as:
//
// init<int, optional<char, long>, int> // BAD trailing int
// init<optional<char, long>, optional<char> > // BAD optional used twice
//
///////////////////////////////////////////////////////////////////////////
template <int N>
struct check_init_params_helper {
template <class ListT>
struct apply {
// case where size of sequence is not zero
typedef typename mpl::pop_front<ListT>::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<typename mpl::at_c<0, ListT>::type>::value,
size_of_rest = mpl::size<rest>::value,
rest_is_nil = (size_of_rest == 0),
is_ok = first_is_optional ? rest_is_nil :
check_init_params_helper<size_of_rest>
::template apply<rest>::is_ok
};
};
};
template <>
struct check_init_params_helper<0> {
// case where size of sequence is zero
template <class ListT>
struct apply {
enum { is_ok = true };
};
};
struct init_base {};
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct check_init_params : init_base {
typedef mpl::list<BOOST_PYTHON_TEMPLATE_ARGS> params;
BOOST_STATIC_ASSERT
(
check_init_params_helper<mpl::size<params>::value>
::template apply<params>::is_ok
);
};
///////////////////////////////////////////////////////////////////////////
//
// count_optional_types [ and helpers ]
//
// count_optional_types<T0..TN>::value computes the number of
// optional types (see init and optional below). For example:
//
// init<int, string, optional<char, long, double> >::value == 3
//
///////////////////////////////////////////////////////////////////////////
template <class T>
struct count_optionals1 {
BOOST_STATIC_CONSTANT(int, value = 0);
};
template <class T>
struct count_optionals2 {
BOOST_STATIC_CONSTANT(
int, value = mpl::size<typename T::type>::value + 1);
};
template <class T>
struct count_optionals
: mpl::if_c<
is_optional<T>::value // if
, count_optionals2<T> // then
, count_optionals1<T> // else
>::type
struct is_optional : is_optional_impl<T>
{
typedef mpl::bool_c<is_optional_impl<T>::value> type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_optional,(T)) // needed for MSVC & Borland
};
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct count_optional_types {
BOOST_STATIC_CONSTANT(int, value =
count_optionals<T0>::value +
count_optionals<T1>::value +
count_optionals<T2>::value
);
};
#endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
} // namespace detail
///////////////////////////////////////////////////////////////////////////////
//
// init
//
// init<T0...TN>::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 <BOOST_PYTHON_TEMPLATE_TYPES>
struct init : detail::check_init_params<BOOST_PYTHON_TEMPLATE_ARGS>
struct init //: detail::check_init_params<BOOST_PYTHON_TEMPLATE_ARGS>
{
typedef mpl::list<T0> l0;
BOOST_PP_REPEAT
(BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BOOST_PYTHON_APPEND_TO_INIT, 0)
typedef mpl::list<BOOST_PYTHON_TEMPLATE_ARGS> signature_;
typedef typename mpl::end<signature_>::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<mpl::_>
>::type opt;
BOOST_STATIC_CONSTANT(int, n_arguments = mpl::size<type>::value);
BOOST_STATIC_CONSTANT(int, n_defaults =
(detail::count_optional_types<BOOST_PYTHON_TEMPLATE_ARGS>::value)
);
// Check to make sure the optional<> element, if any, is the last one
typedef typename mpl::apply_if<
is_same<opt,finish>
, mpl::identity<opt>
, mpl::next<opt>
>::type expected_finish;
BOOST_STATIC_ASSERT((is_same<expected_finish, finish>::value));
typedef typename mpl::apply_if<
is_same<opt,finish>
, mpl::list<>
, opt
>::type optional_args;
// Count the number of default args
BOOST_STATIC_CONSTANT(int, n_defaults = mpl::size<optional_args>::value);
typedef typename mpl::iterator_range<
typename mpl::begin<signature_>::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<mpl::_1, mpl::_2>
>::type reversed_required;
typedef typename mpl::fold<
optional_args
, reversed_required
, mpl::push_front<mpl::_1, mpl::_2>
>::type reversed_args;
// Count the maximum number of arguments
BOOST_STATIC_CONSTANT(int, n_arguments = mpl::size<reversed_args>::value);
};
///////////////////////////////////////////////////////////////////////////////
@@ -328,56 +181,69 @@ struct init : detail::check_init_params<BOOST_PYTHON_TEMPLATE_ARGS>
//
///////////////////////////////////////////////////////////////////////////////
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct optional {
typedef mpl::list<BOOST_PYTHON_TEMPLATE_ARGS> type;
struct optional
: mpl::list<BOOST_PYTHON_TEMPLATE_ARGS>
{
};
namespace detail {
namespace detail
{
template <class ClassT, class CallPoliciesT, class ReversedArgs>
void def_init_reversed(ClassT& cl, ReversedArgs const&, CallPoliciesT const& policies, char const* doc)
{
typedef typename mpl::fold<
ReversedArgs
, mpl::list<>
, mpl::push_front<mpl::_1,mpl::_2>
>::type args;
cl.def_init(args(), policies, doc);
}
///////////////////////////////////////////////////////////////////////////////
//
// define_class_init_helper<N>::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<N-1>::apply with one less arguments (the
// rightmost argument is shaved off)
//
///////////////////////////////////////////////////////////////////////////////
template <int N>
struct define_class_init_helper {
///////////////////////////////////////////////////////////////////////////////
//
// define_class_init_helper<N>::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<N-1>::apply with one less arguments (the
// rightmost argument is shaved off)
//
///////////////////////////////////////////////////////////////////////////////
template <int N>
struct define_class_init_helper {
template <class ClassT, class CallPoliciesT, class ReversedArgs>
static void apply(ClassT& cl, CallPoliciesT const& policies, ReversedArgs const& args, char const* doc)
{
def_init_reversed(cl, args, policies, doc);
template <class ClassT, class CallPoliciesT, class ArgsT>
static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc)
{
cl.def_init(args, policies, doc);
typename mpl::pop_back<ArgsT>::type next;
define_class_init_helper<N-1>::apply(cl, policies, next, doc);
}
};
typename mpl::pop_front<ReversedArgs>::type next;
define_class_init_helper<N-1>::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 <class ClassT, class CallPoliciesT, class ArgsT>
static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc)
{
cl.def_init(args, policies, doc);
}
};
template <class ClassT, class CallPoliciesT, class ReversedArgs>
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 <class ClassT, class CallPoliciesT, class InitT>
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<InitT::n_defaults>::apply(cl, policies, args_t(), doc);
typedef typename InitT::reversed_args reversed_args;
detail::define_class_init_helper<InitT::n_defaults>::apply(cl, policies, reversed_args(), doc);
}
}} // namespace boost::python