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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user