From b3910f4e4d758cd2219b9a500e12dc8c8e46407b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 7 Sep 2003 16:56:05 +0000 Subject: [PATCH] Support for wrapping function objects and classes which use virtual inheritance. Completely killed off member_function_cast! [SVN r19945] --- include/boost/python/class.hpp | 77 +++--- include/boost/python/detail/defaults_def.hpp | 256 +++++++++--------- .../python/detail/make_keyword_range_fn.hpp | 19 +- .../python/detail/member_function_cast.hpp | 118 -------- include/boost/python/make_function.hpp | 78 +++++- include/boost/python/pure_virtual.hpp | 9 +- include/boost/python/signature.hpp | 98 +++++-- test/Jamfile | 1 - test/member_function_cast.cpp | 55 ---- test/polymorphism.cpp | 4 +- 10 files changed, 340 insertions(+), 375 deletions(-) delete mode 100644 include/boost/python/detail/member_function_cast.hpp delete mode 100644 test/member_function_cast.cpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 84ac59db..b9fbc3f5 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -29,7 +29,6 @@ # include # include -# include # include # include @@ -363,56 +362,28 @@ class class_ : public objects::class_base template self& add_property(char const* name, Get fget) { - base::add_property( - name - , object( - detail::member_function_cast::stage1(fget).stage2((T*)0).stage3(fget) - ) - ); - + base::add_property(name, make_fn(fget)); return *this; } template self& add_property(char const* name, Get fget, Set fset) { - base::add_property( - name - , object( - detail::member_function_cast::stage1(fget).stage2((T*)0).stage3(fget) - ) - , object( - detail::member_function_cast::stage1(fset).stage2((T*)0).stage3(fset) - ) - ); + base::add_property(name, make_fn(fget), make_fn(fset)); return *this; } template self& add_static_property(char const* name, Get fget) { - base::add_static_property( - name - , object( - detail::member_function_cast::stage1(fget).stage2((T*)0).stage3(fget) - ) - ); - + base::add_static_property(name, object(fget)); return *this; } template self& add_static_property(char const* name, Get fget, Set fset) { - base::add_static_property( - name - , object( - detail::member_function_cast::stage1(fget).stage2((T*)0).stage3(fget) - ) - , object( - detail::member_function_cast::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 + 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 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::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_()); } diff --git a/include/boost/python/detail/defaults_def.hpp b/include/boost/python/detail/defaults_def.hpp index 64ef70cc..6c808703 100644 --- a/include/boost/python/detail/defaults_def.hpp +++ b/include/boost/python/detail/defaults_def.hpp @@ -37,8 +37,13 @@ namespace objects namespace detail { - template 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 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::stage1(f).stage2((wrapped_type*)0).stage3(f) - , policies, kw) - , doc); + f, policies, kw, get_signature(f, (wrapped_type*)0)) + , doc + ); } template @@ -80,7 +84,7 @@ namespace detail , doc); } - // For backward compatibility + // For backward compatibility -- is this obsolete? template 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 // 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 struct define_stub_function {}; @@ -126,129 +130,137 @@ namespace detail (3, (0, BOOST_PYTHON_MAX_ARITY, )) #include BOOST_PP_ITERATE() + + // } + + // This helper template struct does the actual recursive + // definition. There's a generic version + // define_with_defaults_helper 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. The general case recursively calls + // define_with_defaults_helper::def until it reaches the + // terminal case case define_with_defaults_helper<0>. + template + struct define_with_defaults_helper { -/////////////////////////////////////////////////////////////////////////////// -// -// define_with_defaults_helper -// -// This helper template struct does the actual recursive definition. -// There's a generic version define_with_defaults_helper 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. The general case recursively calls -// define_with_defaults_helper::def until it reaches the -// terminal case case define_with_defaults_helper<0>. -// -/////////////////////////////////////////////////////////////////////////////// - template - struct define_with_defaults_helper { + template + 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::define(name, stubs, kw, policies, name_space, doc); - template - 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::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::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::def(name, stubs, kw, policies, name_space, doc); + } + }; - template - 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 -// void bar(int, int) mpl::list -// void C::foo(int) mpl::list -// -/////////////////////////////////////////////////////////////////////////////// - template - inline void - define_with_defaults( - char const* name, - OverloadsT const& overloads, - NameSpaceT& name_space, - SigT const&) - { - typedef typename mpl::front::type return_type; - typedef typename OverloadsT::void_return_type void_return_type; - typedef typename OverloadsT::non_void_return_type non_void_return_type; + template + 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::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 + // void bar(int, int) mpl::vector + // void C::foo(int) mpl::vector + // + template + inline void + define_with_defaults( + char const* name, + OverloadsT const& overloads, + NameSpaceT& name_space, + SigT const&) + { + typedef typename mpl::front::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::value); + typedef typename mpl::if_c< + boost::is_same::value + , void_return_type + , non_void_return_type + >::type stubs_type; - typedef typename stubs_type::template gen gen_type; - define_with_defaults_helper::def( - name - , gen_type() - , overloads.keywords() - , overloads.call_policies() - , name_space - , overloads.doc_string()); - } + BOOST_STATIC_ASSERT( + (stubs_type::max_args) <= mpl::size::value); + + typedef typename stubs_type::template gen gen_type; + define_with_defaults_helper::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) diff --git a/include/boost/python/detail/make_keyword_range_fn.hpp b/include/boost/python/detail/make_keyword_range_fn.hpp index 27de203a..573eea4f 100644 --- a/include/boost/python/detail/make_keyword_range_fn.hpp +++ b/include/boost/python/detail/make_keyword_range_fn.hpp @@ -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 -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 +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 diff --git a/include/boost/python/detail/member_function_cast.hpp b/include/boost/python/detail/member_function_cast.hpp deleted file mode 100644 index 568c13cc..00000000 --- a/include/boost/python/detail/member_function_cast.hpp +++ /dev/null @@ -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 - -# include -# include - -# include -# include -# include - -# include -# include - -namespace boost { namespace python { namespace detail { - -template -struct cast_helper -{ - struct yes_helper - { - static FT stage3(FT x) { return x; } - }; - - struct no_helper - { - template - 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 - static non_member_function_cast_impl stage1(T) { return non_member_function_cast_impl(); } - - template - static non_member_function_cast_impl stage2(T) { return non_member_function_cast_impl(); } - - template - T stage3(T x) { return x; } -}; - -template -struct member_function_cast_impl -{ -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - template - 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, )) -# include BOOST_PP_ITERATE() -}; - -template -struct member_function_cast -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - : member_function_cast_impl -# else - : mpl::if_c< - is_member_function_pointer::value - , member_function_cast_impl - , 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, )) -# 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 - stage1(R (S::*)( P ) Q) - { - return cast_helper(); - } - -# undef P -# undef N -# undef Q - -#endif diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index 91db7c88..ba3dc8b9 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -9,7 +9,7 @@ # include # include -# include +# include # include # include @@ -64,13 +64,41 @@ namespace detail detail::caller(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 + 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_() + ); + } + + template + 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 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 -object make_function(F f, CallPolicies const& policies, Keywords const& keywords) +template +object make_function( + F f + , CallPolicies const& policies + , KeywordsOrSignature const& keywords_or_signature) +{ + typedef typename + detail::is_reference_to_keywords::type + is_kw; + + return detail::make_function_dispatch( + f + , policies + , keywords_or_signature + , is_kw() + ); +} + +template +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_() - ); + ); } +// } }} diff --git a/include/boost/python/pure_virtual.hpp b/include/boost/python/pure_virtual.hpp index eb7e8a45..85503787 100755 --- a/include/boost/python/pure_virtual.hpp +++ b/include/boost/python/pure_virtual.hpp @@ -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 typename replace_front2::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(pure_virtual_called) , default_call_policies() - , args_from_python() , detail::error_signature(detail::get_signature(m_pmf)) ) ); diff --git a/include/boost/python/signature.hpp b/include/boost/python/signature.hpp index 0d20f8ff..82001b2b 100644 --- a/include/boost/python/signature.hpp +++ b/include/boost/python/signature.hpp @@ -14,6 +14,9 @@ # include +# include +# include + # include # include # include @@ -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 +struct most_derived +{ + typedef typename mpl::if_< + is_convertible + , C1 + , C2 + >::type type; +}; + +// { +// The following macros generate expansions for:: // // template -// inline mpl::list -// get_signature(RT(*)(T0...TN)) +// inline mpl::vector +// get_signature(RT(*)(T0...TN), void* = 0) // { // return mpl::list(); // } // -// And, for an appropriate assortment of cv-qualifications +// And, for an appropriate assortment of cv-qualifications:: // // template -// inline mpl::list +// inline mpl::vector // get_signature(RT(ClassT::*)(T0...TN) cv)) // { // return mpl::list(); // } // -// 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 +// inline mpl::vector< +// RT +// , typename most_derived::type& +// , T0...TN +// > +// get_signature(RT(ClassT::*)(T0...TN) cv), Target*) +// { +// return mpl::list(); +// } // -/////////////////////////////////////////////////////////////////////////////// +// 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, )) # 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::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::type& + BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) + >(); +} + # undef Q # undef N diff --git a/test/Jamfile b/test/Jamfile index 9895e96a..40296bf4 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -161,7 +161,6 @@ local UNIT_TEST_PROPERTIES = $(PYTHON_PROPERTIES) BOOST_PYTHON_SUPPRESS_ run indirect_traits_test.cpp ; run destroy_test.cpp ; run pointer_type_id_test.cpp ../../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) ; diff --git a/test/member_function_cast.cpp b/test/member_function_cast.cpp deleted file mode 100644 index a754fd36..00000000 --- a/test/member_function_cast.cpp +++ /dev/null @@ -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 -#include -#include -#include - -using namespace boost; - -template -void assert_same(S, type* = 0) -{ - BOOST_STATIC_ASSERT((is_same::value)); -} - -template -void assert_mf_cast(F f, type* = 0, type* = 0) -{ - assert_same( - python::detail::member_function_cast::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(&X::f); - assert_mf_cast(&X::g); - - assert_mf_cast(&Z::f); - assert_mf_cast(&Z::g); - - assert_mf_cast(3); - assert_mf_cast(X()); - return 0; -} diff --git a/test/polymorphism.cpp b/test/polymorphism.cpp index 48d269fb..1ee07374 100644 --- a/test/polymorphism.cpp +++ b/test/polymorphism.cpp @@ -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") + .def("g", &P::g) // make sure virtual inheritance doesn't interfere ; }