88
99# include < boost/python/class_fwd.hpp>
1010# include < boost/python/object/class.hpp>
11- # include < boost/python/bases.hpp>
1211
12+ # include < boost/python/bases.hpp>
1313# include < boost/python/object.hpp>
14-
1514# include < boost/python/type_id.hpp>
16- # include < boost/python/object/class_converters.hpp>
15+ # include < boost/python/data_members.hpp>
16+ # include < boost/python/make_function.hpp>
17+ # include < boost/python/signature.hpp>
18+ # include < boost/python/init.hpp>
19+ # include < boost/python/args_fwd.hpp>
20+
1721# include < boost/type_traits/ice.hpp>
18- # include < boost/type_traits/same_traits.hpp>
22+ # include < boost/type_traits/is_same.hpp>
23+ # include < boost/type_traits/is_convertible.hpp>
24+ # include < boost/type_traits/is_member_function_pointer.hpp>
25+ # include < boost/type_traits/is_polymorphic.hpp>
26+
1927# include < boost/mpl/size.hpp>
2028# include < boost/mpl/for_each.hpp>
2129# include < boost/mpl/bool_c.hpp>
30+ # include < boost/mpl/logical/not.hpp>
31+
2232# include < boost/python/object/select_holder.hpp>
2333# include < boost/python/object/class_wrapper.hpp>
2434# include < boost/python/object/make_instance.hpp>
25- # include < boost/python/data_members.hpp>
26- # include < boost/utility.hpp>
2735# include < boost/python/object/pickle_support.hpp>
28- # include < boost/python/make_function.hpp>
2936# include < boost/python/object/add_to_namespace.hpp>
30- # include < boost/python/signature.hpp>
31- # include < boost/python/init.hpp>
32- # include < boost/python/args_fwd.hpp>
37+ # include < boost/python/object/class_converters.hpp>
3338
3439# include < boost/python/detail/string_literal.hpp>
35-
3640# include < boost/python/detail/overloads_fwd.hpp>
3741# include < boost/python/detail/operator_id.hpp>
3842# include < boost/python/detail/member_function_cast.hpp>
3943# include < boost/python/detail/def_helper.hpp>
4044# include < boost/python/detail/force_instantiate.hpp>
4145
46+ # include < boost/utility.hpp>
47+
4248namespace boost { namespace python {
4349
4450enum no_init_t { no_init };
@@ -89,6 +95,54 @@ namespace detail
8995 {
9096 SelectHolder::register_ ();
9197 }
98+
99+ namespace error
100+ {
101+ //
102+ // A meta-assertion mechanism which prints nice error messages and
103+ // backtraces on lots of compilers. Usage:
104+ //
105+ // assertion<C>::failed
106+ //
107+ // where C is an MPL metafunction class
108+ //
109+
110+ template <class C > struct assertion_failed { };
111+ template <class C > struct assertion_ok { typedef C failed; };
112+
113+ template <class C >
114+ struct assertion
115+ : mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
116+ {};
117+
118+ //
119+ // Checks for validity of arguments used to define virtual
120+ // functions with default implementations.
121+ //
122+
123+ template <class Default >
124+ void not_a_derived_class_member (Default) {}
125+
126+ template <class T , class Fn >
127+ struct virtual_function_default
128+ # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
129+ : assertion<is_polymorphic<T> >::failed
130+ , assertion<is_member_function_pointer<Fn> >::failed
131+ # endif
132+ {
133+ template <class Default >
134+ static void
135+ must_be_derived_class_member (Default const &)
136+ {
137+ typedef typename assertion<mpl::logical_not<is_same<Default,Fn> > >::failed test0;
138+ # if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
139+ typedef typename assertion<is_polymorphic<T> >::failed test1;
140+ typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
141+ # endif
142+ not_a_derived_class_member<Default>(Fn ());
143+ }
144+ };
145+ }
92146}
93147
94148// This is the primary mechanism through which users will expose
@@ -313,6 +367,22 @@ class class_ : public objects::class_base
313367 // things which are already wrapped into callable python::object
314368 // instances and everything else.
315369 //
370+ template <class F , class A1 >
371+ inline void def_impl (
372+ char const * name
373+ , F f
374+ , detail::def_helper<A1> const & helper
375+ , object const *)
376+ {
377+ // It's too late to specify anything other than docstrings, if
378+ // the callable object is already wrapped.
379+ BOOST_STATIC_ASSERT (
380+ (is_same<char const *,A1>::value
381+ || detail::is_string_literal<A1>::value));
382+
383+ objects::add_to_namespace (*this , name, f, helper.doc ());
384+ }
385+
316386 template <class Fn , class Helper >
317387 inline void def_impl (
318388 char const * name
@@ -327,24 +397,36 @@ class class_ : public objects::class_base
327397 detail::member_function_cast<T,Fn>::stage1 (fn).stage2 ((T*)0 ).stage3 (fn)
328398 , helper.policies (), helper.keywords ())
329399 , helper.doc ());
400+
401+ this ->def_default (name, fn, helper, mpl::bool_c<Helper::has_default_implementation>());
330402 }
331403
332- template <class F , class A1 >
333- inline void def_impl (
404+ //
405+ // These two overloads handle the definition of default
406+ // implementation overloads for virtual functions. The second one
407+ // handles the case where no default implementation was specified.
408+ //
409+ template <class Fn , class Helper >
410+ inline void def_default (
334411 char const * name
335- , F f
336- , detail::def_helper<A1> const & helper
337- , object const * )
412+ , Fn fn
413+ , Helper const & helper
414+ , mpl::bool_c< true > )
338415 {
339- // It's too late to specify anything other than docstrings, if
340- // the callable object is already wrapped.
341- BOOST_STATIC_ASSERT (
342- (is_same<char const *,A1>::value
343- || detail::is_string_literal<A1>::value));
344-
345- objects::add_to_namespace (*this , name, f, helper.doc ());
416+ detail::error::virtual_function_default<T,Fn>::must_be_derived_class_member (
417+ helper.default_implementation ());
418+
419+ objects::add_to_namespace (
420+ *this , name,
421+ make_function (
422+ helper.default_implementation (), helper.policies (), helper.keywords ())
423+ );
346424 }
347-
425+
426+ template <class Fn , class Helper >
427+ inline void def_default (char const *, Fn, Helper const &, mpl::bool_c<false >)
428+ { }
429+
348430 //
349431 // These two overloads discriminate between def() as applied to
350432 // regular functions and def() as applied to the result of
0 commit comments