mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 06:02:14 +00:00
Support for wrapping function objects and classes which use virtual
inheritance. Completely killed off member_function_cast! [SVN r19945]
This commit is contained in:
@@ -29,7 +29,6 @@
|
||||
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
|
||||
@@ -363,56 +362,28 @@ class class_ : public objects::class_base
|
||||
template <class Get>
|
||||
self& add_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
);
|
||||
|
||||
base::add_property(name, make_fn(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
, object(
|
||||
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
|
||||
)
|
||||
);
|
||||
base::add_property(name, make_fn(fget), make_fn(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get>
|
||||
self& add_static_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_static_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
);
|
||||
|
||||
base::add_static_property(name, object(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_static_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_static_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
, object(
|
||||
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
|
||||
)
|
||||
);
|
||||
base::add_static_property(name, object(fget), object(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -444,6 +415,30 @@ class class_ : public objects::class_base
|
||||
}
|
||||
private: // helper functions
|
||||
|
||||
|
||||
// Builds a method for this class around the given [member]
|
||||
// function pointer or object, appropriately adjusting the type of
|
||||
// the first signature argument so that if f is a member of a
|
||||
// (possibly not wrapped) base class of T, an lvalue argument of
|
||||
// type T will be required.
|
||||
//
|
||||
// {
|
||||
template <class F>
|
||||
object make_fn(F const& f)
|
||||
{
|
||||
return make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
|
||||
}
|
||||
|
||||
object
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
const&
|
||||
# endif
|
||||
make_fn(object const& x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
// }
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readonly_impl(
|
||||
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
|
||||
@@ -501,12 +496,16 @@ class class_ : public objects::class_base
|
||||
)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
|
||||
, helper.policies(), helper.keywords())
|
||||
, helper.doc());
|
||||
*this
|
||||
, name
|
||||
, make_function(
|
||||
fn
|
||||
, helper.policies()
|
||||
, helper.keywords()
|
||||
, detail::get_signature(fn, (T*)0)
|
||||
)
|
||||
, helper.doc()
|
||||
);
|
||||
|
||||
this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
|
||||
}
|
||||
|
||||
@@ -37,8 +37,13 @@ namespace objects
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class F> struct member_function_cast;
|
||||
|
||||
// Called as::
|
||||
//
|
||||
// name_space_def(ns, "func", func, kw, policies, docstring, &ns)
|
||||
//
|
||||
// Dispatch to properly add f to namespace ns.
|
||||
//
|
||||
// { define_stub_function helpers
|
||||
template <class Func, class CallPolicies, class NameSpaceT>
|
||||
static void name_space_def(
|
||||
NameSpaceT& name_space
|
||||
@@ -55,10 +60,9 @@ namespace detail
|
||||
objects::add_to_namespace(
|
||||
name_space, name,
|
||||
detail::make_keyword_range_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
member_function_cast<wrapped_type,Func>::stage1(f).stage2((wrapped_type*)0).stage3(f)
|
||||
, policies, kw)
|
||||
, doc);
|
||||
f, policies, kw, get_signature(f, (wrapped_type*)0))
|
||||
, doc
|
||||
);
|
||||
}
|
||||
|
||||
template <class Func, class CallPolicies>
|
||||
@@ -80,7 +84,7 @@ namespace detail
|
||||
, doc);
|
||||
}
|
||||
|
||||
// For backward compatibility
|
||||
// For backward compatibility -- is this obsolete?
|
||||
template <class Func, class CallPolicies, class NameSpaceT>
|
||||
static void name_space_def(
|
||||
NameSpaceT& name_space
|
||||
@@ -94,10 +98,10 @@ namespace detail
|
||||
{
|
||||
name_space.def(name, f, policies, doc);
|
||||
}
|
||||
// }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This Boost PP code generates expansions for
|
||||
|
||||
// Expansions of ::
|
||||
//
|
||||
// template <typename OverloadsT, typename NameSpaceT>
|
||||
// inline void
|
||||
@@ -107,7 +111,7 @@ namespace detail
|
||||
// name_space.def(name, &OverloadsT::func_N);
|
||||
// }
|
||||
//
|
||||
// where N runs from 0 to BOOST_PYTHON_MAX_ARITY
|
||||
// where N runs from 0 to BOOST_PYTHON_MAX_ARITY.
|
||||
//
|
||||
// The set of overloaded functions (define_stub_function) expects:
|
||||
//
|
||||
@@ -118,7 +122,7 @@ namespace detail
|
||||
// (see defaults_gen.hpp)
|
||||
// 5. char const* name: doc string
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// {
|
||||
template <int N>
|
||||
struct define_stub_function {};
|
||||
|
||||
@@ -126,129 +130,137 @@ namespace detail
|
||||
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/defaults_def.hpp>))
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
// }
|
||||
|
||||
// This helper template struct does the actual recursive
|
||||
// definition. There's a generic version
|
||||
// define_with_defaults_helper<N> and a terminal case
|
||||
// define_with_defaults_helper<0>. The struct and its
|
||||
// specialization has a sole static member function def that
|
||||
// expects:
|
||||
//
|
||||
// 1. char const* name: function name that will be
|
||||
// visible to python
|
||||
//
|
||||
// 2. OverloadsT: a function overloads struct
|
||||
// (see defaults_gen.hpp)
|
||||
//
|
||||
// 3. NameSpaceT& name_space: a python::class_ or
|
||||
// python::module instance
|
||||
//
|
||||
// 4. char const* name: doc string
|
||||
//
|
||||
// The def static member function calls a corresponding
|
||||
// define_stub_function<N>. The general case recursively calls
|
||||
// define_with_defaults_helper<N-1>::def until it reaches the
|
||||
// terminal case case define_with_defaults_helper<0>.
|
||||
template <int N>
|
||||
struct define_with_defaults_helper {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// define_with_defaults_helper<N>
|
||||
//
|
||||
// This helper template struct does the actual recursive definition.
|
||||
// There's a generic version define_with_defaults_helper<N> and a
|
||||
// terminal case define_with_defaults_helper<0>. The struct and its
|
||||
// specialization has a sole static member function def that expects:
|
||||
//
|
||||
// 1. char const* name: function name that will be visible to python
|
||||
// 2. OverloadsT: a function overloads struct (see defaults_gen.hpp)
|
||||
// 3. NameSpaceT& name_space: a python::class_ or python::module instance
|
||||
// 4. char const* name: doc string
|
||||
//
|
||||
// The def static member function calls a corresponding
|
||||
// define_stub_function<N>. The general case recursively calls
|
||||
// define_with_defaults_helper<N-1>::def until it reaches the
|
||||
// terminal case case define_with_defaults_helper<0>.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <int N>
|
||||
struct define_with_defaults_helper {
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the NTH stub function of stubs
|
||||
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
|
||||
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the NTH stub function of stubs
|
||||
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
|
||||
|
||||
if (kw.second > kw.first)
|
||||
--kw.second;
|
||||
|
||||
// call the next define_with_defaults_helper
|
||||
define_with_defaults_helper<N-1>::def(name, stubs, kw, policies, name_space, doc);
|
||||
}
|
||||
};
|
||||
if (kw.second > kw.first)
|
||||
--kw.second;
|
||||
|
||||
///////////////////////////////////////
|
||||
template <>
|
||||
struct define_with_defaults_helper<0> {
|
||||
// call the next define_with_defaults_helper
|
||||
define_with_defaults_helper<N-1>::def(name, stubs, kw, policies, name_space, doc);
|
||||
}
|
||||
};
|
||||
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range const& kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the Oth stub function of stubs
|
||||
define_stub_function<0>::define(name, stubs, kw, policies, name_space, doc);
|
||||
// return
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct define_with_defaults_helper<0> {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// define_with_defaults
|
||||
//
|
||||
// 1. char const* name: function name that will be visible to python
|
||||
// 2. OverloadsT: a function overloads struct (see defaults_gen.hpp)
|
||||
// 3. CallPolicies& policies: Call policies
|
||||
// 4. NameSpaceT& name_space: a python::class_ or python::module instance
|
||||
// 5. SigT sig: Function signature typelist (see defaults_gen.hpp)
|
||||
// 6. char const* name: doc string
|
||||
//
|
||||
// This is the main entry point. This function recursively defines all
|
||||
// stub functions of StubT (see defaults_gen.hpp) in NameSpaceT name_space which
|
||||
// can be either a python::class_ or a python::module. The sig argument
|
||||
// is a typelist that specifies the return type, the class (for member
|
||||
// functions, and the arguments. Here are some SigT examples:
|
||||
//
|
||||
// int foo(int) mpl::list<int, int>
|
||||
// void bar(int, int) mpl::list<void, int, int>
|
||||
// void C::foo(int) mpl::list<void, C, int>
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <class OverloadsT, class NameSpaceT, class SigT>
|
||||
inline void
|
||||
define_with_defaults(
|
||||
char const* name,
|
||||
OverloadsT const& overloads,
|
||||
NameSpaceT& name_space,
|
||||
SigT const&)
|
||||
{
|
||||
typedef typename mpl::front<SigT>::type return_type;
|
||||
typedef typename OverloadsT::void_return_type void_return_type;
|
||||
typedef typename OverloadsT::non_void_return_type non_void_return_type;
|
||||
template <class StubsT, class CallPolicies, class NameSpaceT>
|
||||
static void
|
||||
def(
|
||||
char const* name,
|
||||
StubsT stubs,
|
||||
keyword_range const& kw,
|
||||
CallPolicies const& policies,
|
||||
NameSpaceT& name_space,
|
||||
char const* doc)
|
||||
{
|
||||
// define the Oth stub function of stubs
|
||||
define_stub_function<0>::define(name, stubs, kw, policies, name_space, doc);
|
||||
// return
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
boost::is_same<void, return_type>::value
|
||||
, void_return_type
|
||||
, non_void_return_type
|
||||
>::type stubs_type;
|
||||
// define_with_defaults
|
||||
//
|
||||
// 1. char const* name: function name that will be
|
||||
// visible to python
|
||||
//
|
||||
// 2. OverloadsT: a function overloads struct
|
||||
// (see defaults_gen.hpp)
|
||||
//
|
||||
// 3. CallPolicies& policies: Call policies
|
||||
// 4. NameSpaceT& name_space: a python::class_ or
|
||||
// python::module instance
|
||||
//
|
||||
// 5. SigT sig: Function signature typelist
|
||||
// (see defaults_gen.hpp)
|
||||
//
|
||||
// 6. char const* name: doc string
|
||||
//
|
||||
// This is the main entry point. This function recursively
|
||||
// defines all stub functions of StubT (see defaults_gen.hpp) in
|
||||
// NameSpaceT name_space which can be either a python::class_ or
|
||||
// a python::module. The sig argument is a typelist that
|
||||
// specifies the return type, the class (for member functions,
|
||||
// and the arguments. Here are some SigT examples:
|
||||
//
|
||||
// int foo(int) mpl::vector<int, int>
|
||||
// void bar(int, int) mpl::vector<void, int, int>
|
||||
// void C::foo(int) mpl::vector<void, C, int>
|
||||
//
|
||||
template <class OverloadsT, class NameSpaceT, class SigT>
|
||||
inline void
|
||||
define_with_defaults(
|
||||
char const* name,
|
||||
OverloadsT const& overloads,
|
||||
NameSpaceT& name_space,
|
||||
SigT const&)
|
||||
{
|
||||
typedef typename mpl::front<SigT>::type return_type;
|
||||
typedef typename OverloadsT::void_return_type void_return_type;
|
||||
typedef typename OverloadsT::non_void_return_type non_void_return_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
(stubs_type::max_args) <= mpl::size<SigT>::value);
|
||||
typedef typename mpl::if_c<
|
||||
boost::is_same<void, return_type>::value
|
||||
, void_return_type
|
||||
, non_void_return_type
|
||||
>::type stubs_type;
|
||||
|
||||
typedef typename stubs_type::template gen<SigT> gen_type;
|
||||
define_with_defaults_helper<stubs_type::n_funcs-1>::def(
|
||||
name
|
||||
, gen_type()
|
||||
, overloads.keywords()
|
||||
, overloads.call_policies()
|
||||
, name_space
|
||||
, overloads.doc_string());
|
||||
}
|
||||
BOOST_STATIC_ASSERT(
|
||||
(stubs_type::max_args) <= mpl::size<SigT>::value);
|
||||
|
||||
typedef typename stubs_type::template gen<SigT> gen_type;
|
||||
define_with_defaults_helper<stubs_type::n_funcs-1>::def(
|
||||
name
|
||||
, gen_type()
|
||||
, overloads.keywords()
|
||||
, overloads.call_policies()
|
||||
, name_space
|
||||
, overloads.doc_string());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#endif // DEFAULTS_DEF_JDG20020811_HPP
|
||||
|
||||
#else // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
@@ -21,13 +21,30 @@ namespace boost { namespace python { namespace detail {
|
||||
// F. This version is needed when defining functions with default
|
||||
// arguments, because compile-time information about the number of
|
||||
// keywords is missing for all but the initial function definition.
|
||||
//
|
||||
// {
|
||||
template <class F, class Policies>
|
||||
object make_keyword_range_function(F f, Policies const& policies, keyword_range const& kw)
|
||||
object make_keyword_range_function(
|
||||
F f
|
||||
, Policies const& policies
|
||||
, keyword_range const& kw)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f, policies, args_from_python(), detail::get_signature(f), kw, mpl::int_<0>());
|
||||
}
|
||||
|
||||
template <class F, class Policies, class Signature>
|
||||
object make_keyword_range_function(
|
||||
F f
|
||||
, Policies const& policies
|
||||
, keyword_range const& kw
|
||||
, Signature const& sig)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f, policies, args_from_python(), sig, kw, mpl::int_<0>());
|
||||
}
|
||||
// }
|
||||
|
||||
// Builds an '__init__' function which inserts the given Holder type
|
||||
// in a wrapped C++ class instance. ArgList is an MPL type sequence
|
||||
// describing the C++ argument types to be passed to Holder's
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
# ifndef MEMBER_FUNCTION_CAST_DWA2002311_HPP
|
||||
# define MEMBER_FUNCTION_CAST_DWA2002311_HPP
|
||||
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class S, class FT>
|
||||
struct cast_helper
|
||||
{
|
||||
struct yes_helper
|
||||
{
|
||||
static FT stage3(FT x) { return x; }
|
||||
};
|
||||
|
||||
struct no_helper
|
||||
{
|
||||
template <class T>
|
||||
static T stage3(T x) { return x; }
|
||||
};
|
||||
|
||||
static yes_helper stage2(S*) { return yes_helper(); }
|
||||
static no_helper stage2(void*) { return no_helper(); }
|
||||
};
|
||||
|
||||
struct non_member_function_cast_impl
|
||||
{
|
||||
template <class T>
|
||||
static non_member_function_cast_impl stage1(T) { return non_member_function_cast_impl(); }
|
||||
|
||||
template <class T>
|
||||
static non_member_function_cast_impl stage2(T) { return non_member_function_cast_impl(); }
|
||||
|
||||
template <class T>
|
||||
T stage3(T x) { return x; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct member_function_cast_impl
|
||||
{
|
||||
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
template <class U>
|
||||
static non_member_function_cast_impl stage1(U)
|
||||
{
|
||||
return non_member_function_cast_impl();
|
||||
}
|
||||
# endif
|
||||
|
||||
// Member functions
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, <boost/python/detail/member_function_cast.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
};
|
||||
|
||||
template <class T, class SF>
|
||||
struct member_function_cast
|
||||
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
: member_function_cast_impl<T>
|
||||
# else
|
||||
: mpl::if_c<
|
||||
is_member_function_pointer<SF>::value
|
||||
, member_function_cast_impl<T>
|
||||
, non_member_function_cast_impl
|
||||
>::type
|
||||
# endif
|
||||
{
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
# endif // MEMBER_FUNCTION_CAST_DWA2002311_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
// outer over cv-qualifiers
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/member_function_cast.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 2
|
||||
# line BOOST_PP_LINE(__LINE__, member_function_cast.hpp)
|
||||
// inner over arities
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1))
|
||||
# define P BOOST_PP_ENUM_PARAMS_Z(1, N, A)
|
||||
|
||||
template <
|
||||
class S, class R
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
|
||||
>
|
||||
static cast_helper<S, R (T::*)( P ) Q>
|
||||
stage1(R (S::*)( P ) Q)
|
||||
{
|
||||
return cast_helper<S, R (T::*)( P ) Q>();
|
||||
}
|
||||
|
||||
# undef P
|
||||
# undef N
|
||||
# undef Q
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,7 @@
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/detail/caller.hpp>
|
||||
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
@@ -64,13 +64,41 @@ namespace detail
|
||||
detail::caller<F,ConverterGenerators,CallPolicies,Sig>(f, p)
|
||||
, kw);
|
||||
}
|
||||
}
|
||||
|
||||
// make_function --
|
||||
//
|
||||
// These overloaded functions wrap a function or member function
|
||||
// pointer as a Python object, using optional CallPolicies and
|
||||
// Keywords.
|
||||
// { Helpers for make_function when called with 3 arguments. These
|
||||
// dispatch functions are used to discriminate between the cases
|
||||
// when the 3rd argument is keywords or when it is a signature.
|
||||
//
|
||||
template <class F, class CallPolicies, class Keywords>
|
||||
object make_function_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f
|
||||
, policies
|
||||
, detail::args_from_python()
|
||||
, detail::get_signature(f)
|
||||
, kw.range()
|
||||
, mpl::int_<Keywords::size>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Signature>
|
||||
object make_function_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f
|
||||
, policies
|
||||
, detail::args_from_python()
|
||||
, sig
|
||||
);
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// { These overloaded functions wrap a function or member function
|
||||
// pointer as a Python object, using optional CallPolicies,
|
||||
// Keywords, and/or Signature.
|
||||
template <class F>
|
||||
object make_function(F f)
|
||||
{
|
||||
@@ -85,18 +113,42 @@ object make_function(F f, CallPolicies const& policies)
|
||||
f,policies,detail::args_from_python(), detail::get_signature(f));
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Keywords>
|
||||
object make_function(F f, CallPolicies const& policies, Keywords const& keywords)
|
||||
template <class F, class CallPolicies, class KeywordsOrSignature>
|
||||
object make_function(
|
||||
F f
|
||||
, CallPolicies const& policies
|
||||
, KeywordsOrSignature const& keywords_or_signature)
|
||||
{
|
||||
typedef typename
|
||||
detail::is_reference_to_keywords<KeywordsOrSignature&>::type
|
||||
is_kw;
|
||||
|
||||
return detail::make_function_dispatch(
|
||||
f
|
||||
, policies
|
||||
, keywords_or_signature
|
||||
, is_kw()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F, class CallPolicies, class Keywords, class Signature>
|
||||
object make_function(
|
||||
F f
|
||||
, CallPolicies const& policies
|
||||
, Keywords const& kw
|
||||
, Signature const& sig
|
||||
)
|
||||
{
|
||||
return detail::make_function_aux(
|
||||
f
|
||||
f
|
||||
, policies
|
||||
, detail::args_from_python()
|
||||
, detail::get_signature(f)
|
||||
, keywords.range()
|
||||
, sig
|
||||
, kw.range()
|
||||
, mpl::int_<Keywords::size>()
|
||||
);
|
||||
);
|
||||
}
|
||||
// }
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace detail
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// Given an MPL sequence representing a signature, returns a new MPL
|
||||
// sequence whose return type is replaced by void, and whose first
|
||||
// argument is replaced by C&.
|
||||
// Given an MPL sequence representing a member function [object]
|
||||
// signature, returns a new MPL sequence whose return type is
|
||||
// replaced by void, and whose first argument is replaced by C&.
|
||||
template <class C, class S>
|
||||
typename replace_front2<S,void,C&>::type
|
||||
error_signature(S BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(C))
|
||||
@@ -97,10 +97,9 @@ namespace detail
|
||||
// Add the default implementation which raises the exception
|
||||
c.def(
|
||||
name
|
||||
, detail::make_function_aux(
|
||||
, make_function(
|
||||
detail::nullary_function_adaptor<void(*)()>(pure_virtual_called)
|
||||
, default_call_policies()
|
||||
, args_from_python()
|
||||
, detail::error_signature<held_t>(detail::get_signature(m_pmf))
|
||||
)
|
||||
);
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/enum.hpp>
|
||||
@@ -34,48 +37,80 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The following macros generate expansions for:
|
||||
// A metafunction returning C1 if C1 is derived from C2, and C2
|
||||
// otherwise
|
||||
template <class C1, class C2>
|
||||
struct most_derived
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_convertible<C1*,C2*>
|
||||
, C1
|
||||
, C2
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// {
|
||||
// The following macros generate expansions for::
|
||||
//
|
||||
// template <class RT, class T0... class TN>
|
||||
// inline mpl::list<RT, T0...TN>
|
||||
// get_signature(RT(*)(T0...TN))
|
||||
// inline mpl::vector<RT, T0...TN>
|
||||
// get_signature(RT(*)(T0...TN), void* = 0)
|
||||
// {
|
||||
// return mpl::list<RT, T0...TN>();
|
||||
// }
|
||||
//
|
||||
// And, for an appropriate assortment of cv-qualifications
|
||||
// And, for an appropriate assortment of cv-qualifications::
|
||||
//
|
||||
// template <class RT, class ClassT, class T0... class TN>
|
||||
// inline mpl::list<RT, ClassT cv&, T0...TN>
|
||||
// inline mpl::vector<RT, ClassT&, T0...TN>
|
||||
// get_signature(RT(ClassT::*)(T0...TN) cv))
|
||||
// {
|
||||
// return mpl::list<RT, ClassT&, T0...TN>();
|
||||
// }
|
||||
//
|
||||
// These functions extract the return type, class (for member
|
||||
// functions) and arguments of the input signature and stuffs them in
|
||||
// an mpl::list. Note that cv-qualification is dropped from the
|
||||
// target class; that is a necessary sacrifice to ensure that an
|
||||
// lvalue from_python converter is used.
|
||||
// template <class Target, class RT, class ClassT, class T0... class TN>
|
||||
// inline mpl::vector<
|
||||
// RT
|
||||
// , typename most_derived<Target, ClassT>::type&
|
||||
// , T0...TN
|
||||
// >
|
||||
// get_signature(RT(ClassT::*)(T0...TN) cv), Target*)
|
||||
// {
|
||||
// return mpl::list<RT, ClassT&, T0...TN>();
|
||||
// }
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// There are two forms for invoking get_signature::
|
||||
//
|
||||
// get_signature(f)
|
||||
//
|
||||
// and ::
|
||||
//
|
||||
// get_signature(f,(Target*)0)
|
||||
//
|
||||
// These functions extract the return type, class (for member
|
||||
// functions) and arguments of the input signature and stuff them in
|
||||
// an mpl type sequence. Note that cv-qualification is dropped from
|
||||
// the "hidden this" argument of member functions; that is a
|
||||
// necessary sacrifice to ensure that an lvalue from_python converter
|
||||
// is used. A pointer is not used so that None will be rejected for
|
||||
// overload resolution.
|
||||
//
|
||||
// The second form of get_signature essentially downcasts the "hidden
|
||||
// this" argument of member functions to Target, because the function
|
||||
// may actually be a member of a base class which is not wrapped, and
|
||||
// in that case conversion from python would fail.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 \
|
||||
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
|
||||
|
||||
# include BOOST_PP_ITERATE()
|
||||
# undef BOOST_PYTHON_LIST_INC
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
}} // namespace boost::python
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
|
||||
# undef BOOST_PYTHON_LIST_INC
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
# endif // SIGNATURE_JDG20020813_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
|
||||
@@ -86,7 +121,7 @@ template <
|
||||
class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
|
||||
inline BOOST_PYTHON_LIST_INC(N)<
|
||||
RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
|
||||
get_signature(RT(*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)))
|
||||
get_signature(RT(*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0)
|
||||
{
|
||||
return BOOST_PYTHON_LIST_INC(N)<
|
||||
RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
|
||||
@@ -115,6 +150,29 @@ get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q)
|
||||
>();
|
||||
}
|
||||
|
||||
template <
|
||||
class Target
|
||||
, class RT
|
||||
, class ClassT
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)
|
||||
>
|
||||
inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
|
||||
RT
|
||||
, typename most_derived<Target, ClassT>::type&
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
|
||||
>
|
||||
get_signature(
|
||||
RT(ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q
|
||||
, Target*
|
||||
)
|
||||
{
|
||||
return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
|
||||
RT
|
||||
, BOOST_DEDUCED_TYPENAME most_derived<Target, ClassT>::type&
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
|
||||
>();
|
||||
}
|
||||
|
||||
# undef Q
|
||||
# undef N
|
||||
|
||||
|
||||
@@ -161,7 +161,6 @@ local UNIT_TEST_PROPERTIES = $(PYTHON_PROPERTIES) <define>BOOST_PYTHON_SUPPRESS_
|
||||
run indirect_traits_test.cpp ;
|
||||
run destroy_test.cpp ;
|
||||
run pointer_type_id_test.cpp <lib>../../test/build/boost_test_exec_monitor : : : $(UNIT_TEST_PROPERTIES) ;
|
||||
run member_function_cast.cpp ;
|
||||
run bases.cpp : : : $(UNIT_TEST_PROPERTIES) ;
|
||||
run if_else.cpp ;
|
||||
run pointee.cpp : : : $(UNIT_TEST_PROPERTIES) ;
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/python/detail/member_function_cast.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/type.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
template <class T, class S>
|
||||
void assert_same(S, type<T>* = 0)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((is_same<T,S>::value));
|
||||
}
|
||||
|
||||
template <class Expected, class Target, class F>
|
||||
void assert_mf_cast(F f, type<Expected>* = 0, type<Target>* = 0)
|
||||
{
|
||||
assert_same<Expected>(
|
||||
python::detail::member_function_cast<Target,F>::stage1(f).stage2((Target*)0).stage3(f)
|
||||
);
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
int f() const { return 0; }
|
||||
void g(char*) {}
|
||||
};
|
||||
|
||||
struct Y : X
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct Z : Y
|
||||
{
|
||||
int f() const { return 0; }
|
||||
void g(char*) {}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
assert_mf_cast<int (Y::*)() const, Y>(&X::f);
|
||||
assert_mf_cast<void (Y::*)(char*), Y>(&X::g);
|
||||
|
||||
assert_mf_cast<int (Z::*)() const, Y>(&Z::f);
|
||||
assert_mf_cast<void (Z::*)(char*), Y>(&Z::g);
|
||||
|
||||
assert_mf_cast<int, Y>(3);
|
||||
assert_mf_cast<X, Y>(X());
|
||||
return 0;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ struct P
|
||||
{
|
||||
virtual ~P(){}
|
||||
virtual std::string f() = 0;
|
||||
std::string g() { return "P::g()"; }
|
||||
};
|
||||
|
||||
struct PCallback : P, Callback
|
||||
@@ -37,7 +38,7 @@ struct PCallback : P, Callback
|
||||
}
|
||||
};
|
||||
|
||||
struct Q : P
|
||||
struct Q : virtual P
|
||||
{
|
||||
std::string f() { return "Q::f()"; }
|
||||
};
|
||||
@@ -155,6 +156,7 @@ BOOST_PYTHON_MODULE_INIT(polymorphism_ext)
|
||||
;
|
||||
|
||||
class_<Q, bases<P> >("Q")
|
||||
.def("g", &P::g) // make sure virtual inheritance doesn't interfere
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user