2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

Got init<..> working

[SVN r15073]
This commit is contained in:
Joel de Guzman
2002-08-23 23:30:29 +00:00
parent 1ee7bd2a60
commit d4c50383af
4 changed files with 153 additions and 37 deletions

View File

@@ -31,6 +31,7 @@
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/defaults_def.hpp>
# include <boost/python/signature.hpp>
# include <boost/python/init.hpp>
namespace boost { namespace python {
@@ -165,6 +166,13 @@ class class_ : public objects::class_base
return *this;
}
template <BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_ARITY, class T)>
self& def(init<BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_ARITY, T)> const& i, char const* doc = 0)
{
define_init(*this, i, doc);
return *this;
}
template <class Arg1T, class Arg2T>
self& def(char const* name, Arg1T arg1, Arg2T const& arg2, char const* doc = 0)
{
@@ -238,7 +246,7 @@ class class_ : public objects::class_base
base::add_property(name, object(fget));
return *this;
}
template <class Get, class Set>
self& add_property(char const* name, Get const& fget, Set const& fset)
{

View File

@@ -16,6 +16,7 @@
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/enum_params_with_a_default.hpp>
@@ -26,22 +27,22 @@
#include <boost/preprocessor/dec.hpp>
///////////////////////////////////////////////////////////////////////////////
#define BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT \
#define BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT \
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT \
( \
BOOST_PYTHON_MAX_ARITY, \
typename T, \
class T, \
boost::mpl::null_argument \
) \
#define BPL_IMPL_TEMPLATE_TYPES \
#define BOOST_PYTHON_TEMPLATE_TYPES \
BOOST_PP_ENUM_PARAMS \
( \
BOOST_PYTHON_MAX_ARITY, \
typename T \
class T \
) \
#define BPL_IMPL_TEMPLATE_ARGS \
#define BOOST_PYTHON_TEMPLATE_ARGS \
BOOST_PP_ENUM_PARAMS \
( \
BOOST_PYTHON_MAX_ARITY, \
@@ -51,12 +52,12 @@
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace python {
template <BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT>
struct init;
template <BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT>
struct init; // forward declaration
///////////////////////////////////////
template <BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT>
struct optional;
template <BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT>
struct optional; // forward declaration
namespace detail {
@@ -67,7 +68,7 @@ namespace detail {
// This metaprogram checks if T is nil
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
template <class T>
struct is_nil : public boost::is_same<T, boost::mpl::null_argument> {};
///////////////////////////////////////////////////////////////////////////
@@ -79,13 +80,13 @@ namespace detail {
///////////////////////////////////////////////////////////////////////////
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
template <class T>
struct is_optional {
private:
template <BPL_IMPL_TEMPLATE_TYPES>
static boost::type_traits::yes_type f(optional<BPL_IMPL_TEMPLATE_ARGS>);
template <BOOST_PYTHON_TEMPLATE_TYPES>
static boost::type_traits::yes_type f(optional<BOOST_PYTHON_TEMPLATE_ARGS>);
static boost::type_traits::no_type f(...);
static T t();
@@ -99,14 +100,14 @@ namespace detail {
///////////////////////////////////////
#else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
template <class T>
struct is_optional {
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <BPL_IMPL_TEMPLATE_TYPES>
struct is_optional<optional<BPL_IMPL_TEMPLATE_ARGS> > {
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct is_optional<optional<BOOST_PYTHON_TEMPLATE_ARGS> > {
BOOST_STATIC_CONSTANT(bool, value = true);
};
@@ -227,10 +228,12 @@ namespace detail {
};
};
template <BPL_IMPL_TEMPLATE_TYPES>
struct check_init_params {
struct init_base {};
typedef boost::mpl::type_list<BPL_IMPL_TEMPLATE_ARGS> params;
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct check_init_params : init_base {
typedef boost::mpl::type_list<BOOST_PYTHON_TEMPLATE_ARGS> params;
BOOST_STATIC_ASSERT
(
@@ -273,7 +276,7 @@ namespace detail {
{
};
template <BPL_IMPL_TEMPLATE_TYPES>
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct count_optional_types {
BOOST_STATIC_CONSTANT(int, value =
@@ -295,7 +298,7 @@ namespace detail {
// last in the list.
//
///////////////////////////////////////////////////////////////////////////////
#define BPL_IMPL_APPEND_TO_INIT(INDEX, D) \
#define BOOST_PYTHON_APPEND_TO_INIT(INDEX, D) \
typedef typename detail::append_to_init \
< \
BOOST_PP_CAT(l, INDEX), \
@@ -303,17 +306,19 @@ namespace detail {
>::sequence BOOST_PP_CAT(l, BOOST_PP_INC(INDEX)); \
template <BPL_IMPL_TEMPLATE_TYPES>
struct init : detail::check_init_params<BPL_IMPL_TEMPLATE_ARGS> {
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct init : detail::check_init_params<BOOST_PYTHON_TEMPLATE_ARGS>
{
typedef boost::mpl::type_list<T0> l0;
BOOST_PP_REPEAT
(BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BPL_IMPL_APPEND_TO_INIT, 0);
(BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BOOST_PYTHON_APPEND_TO_INIT, 0);
typedef BOOST_PP_CAT(l, BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY)) sequence;
BOOST_STATIC_CONSTANT(int, n_arguments = boost::mpl::size<sequence>::value);
BOOST_STATIC_CONSTANT(int, n_defaults =
(detail::count_optional_types<BPL_IMPL_TEMPLATE_ARGS>::value)
(detail::count_optional_types<BOOST_PYTHON_TEMPLATE_ARGS>::value)
);
};
@@ -324,19 +329,96 @@ struct init : detail::check_init_params<BPL_IMPL_TEMPLATE_ARGS> {
// optional<T0...TN>::sequence returns a typelist.
//
///////////////////////////////////////////////////////////////////////////////
template <BPL_IMPL_TEMPLATE_TYPES>
template <BOOST_PYTHON_TEMPLATE_TYPES>
struct optional {
typedef boost::mpl::type_list<BPL_IMPL_TEMPLATE_ARGS> sequence;
typedef boost::mpl::type_list<BOOST_PYTHON_TEMPLATE_ARGS> sequence;
};
#undef BPL_IMPL_TEMPLATE_TYPES_WITH_DEFAULT
#undef BPL_IMPL_TEMPLATE_TYPES
#undef BPL_IMPL_TEMPLATE_ARGS
#undef BPL_IMPL_IS_OPTIONAL_VALUE
#undef BPL_IMPL_APPEND_TO_INIT
namespace detail {
}} // namespace boost { namespace python {
///////////////////////////////////////////////////////////////////////////////
//
// 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 ArgsT>
static void apply(ClassT& cl, ArgsT const& args, char const* doc)
{
cl.def_init(args, default_call_policies(), doc);
boost::mpl::pop_back<ArgsT>::sequence next;
define_class_init_helper<N-1>::apply(cl, 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> {
template <class ClassT, class ArgsT>
static void apply(ClassT& cl, ArgsT const& args, char const* doc)
{
cl.def_init(args, default_call_policies(), doc);
}
};
}
///////////////////////////////////////////////////////////////////////////////
//
// define_init
//
// Accepts a class_ and an init-list. Defines a set of constructors for
// the class given the arguments. The init list (see init above) has
// n_defaults (number of default arguments and n_arguments (number of
// actual arguments). This function defines n_defaults + 1 constructors
// for the class. Each constructor after the first has one less argument
// to its right. Example:
//
// init<int, default<char, long, double>
//
// Defines:
//
// __init__(int, char, long, double)
// __init__(int, char, long)
// __init__(int, char)
// __init__(int)
//
///////////////////////////////////////////////////////////////////////////////
template <class ClassT, class InitT>
void
define_init(ClassT& cl, InitT const& i, char const* doc)
{
enum { n_defaults_plus_1 = InitT::n_defaults + 1 };
typedef typename InitT::sequence args_t;
detail::define_class_init_helper<n_defaults_plus_1>::apply(cl, args_t(), doc);
}
}} // namespace boost::python
#undef BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT
#undef BOOST_PYTHON_TEMPLATE_TYPES
#undef BOOST_PYTHON_TEMPLATE_ARGS
#undef BOOST_PYTHON_IS_OPTIONAL_VALUE
#undef BOOST_PYTHON_APPEND_TO_INIT
///////////////////////////////////////////////////////////////////////////////
#endif // INIT_JDG20020820_HPP

View File

@@ -68,6 +68,12 @@ BOOST_PYTHON_FUNCTION_GENERATOR(foo_stubs, foo, 1, 4)
///////////////////////////////////////////////////////////////////////////////
struct X {
X() {}
X(int a, char b = 'D', std::string c = "constructor", double d = 0.0)
: state(format % make_tuple(a, b, c, d))
{}
object
bar(int a, char b = 'D', std::string c = "default", double d = 0.0) const
{
@@ -91,6 +97,14 @@ struct X {
{
return "list(%s); list(%s); bool(%s); " % make_tuple(a, b, c);
}
object
get_state() const
{
return state;
}
object state;
};
BOOST_PYTHON_MEM_FUN_GENERATOR(X_bar_stubs, bar, 1, 4)
@@ -107,6 +121,8 @@ BOOST_PYTHON_MODULE_INIT(defaults_ext)
;
class_<X>("X")
.def(init<int, optional<char, std::string, double> >())
.def("get_state", &X::get_state)
.def("bar", &X::bar, X_bar_stubs())
.def("foo", (object(X::*)(std::string, bool) const)0, X_foo_2_stubs())
.def("foo", (object(X::*)(int, bool) const)0, X_foo_2_stubs())

View File

@@ -44,8 +44,18 @@
'list([0, 1, 2]); list([2, 3, 4]); bool(0); '
>>> x.foo([0,1,2], [2,3,4], True)
'list([0, 1, 2]); list([2, 3, 4]); bool(1); '
>>>
>>> x = X(1)
>>> x.get_state()
'int(1); char(D); string(constructor); double(0.0); '
>>> x = X(1, 'X')
>>> x.get_state()
'int(1); char(X); string(constructor); double(0.0); '
>>> x = X(1, 'X', "Yabadabadoo")
>>> x.get_state()
'int(1); char(X); string(Yabadabadoo); double(0.0); '
>>> x = X(1, 'X', "Phoenix", 3.65)
>>> x.get_state()
'int(1); char(X); string(Phoenix); double(3.65); '
"""