123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // Copyright David Abrahams 2003.
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef PURE_VIRTUAL_DWA2003810_HPP
- # define PURE_VIRTUAL_DWA2003810_HPP
- # include <boost/python/def_visitor.hpp>
- # include <boost/python/default_call_policies.hpp>
- # include <boost/mpl/push_front.hpp>
- # include <boost/mpl/pop_front.hpp>
- # include <boost/python/detail/nullary_function_adaptor.hpp>
- namespace boost { namespace python {
- namespace detail
- {
- //
- // @group Helpers for pure_virtual_visitor. {
- //
-
- // Raises a Python RuntimeError reporting that a pure virtual
- // function was called.
- void BOOST_PYTHON_DECL pure_virtual_called();
- // Replace the two front elements of S with T1 and T2
- template <class S, class T1, class T2>
- struct replace_front2
- {
- // Metafunction forwarding seemed to confound vc6
- typedef typename mpl::push_front<
- typename mpl::push_front<
- typename mpl::pop_front<
- typename mpl::pop_front<
- S
- >::type
- >::type
- , T2
- >::type
- , T1
- >::type type;
- };
- // 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)
- {
- typedef typename replace_front2<S,void,C&>::type r;
- return r();
- }
- //
- // }
- //
- //
- // A def_visitor which defines a method as usual, then adds a
- // corresponding function which raises a "pure virtual called"
- // exception unless it's been overridden.
- //
- template <class PointerToMemberFunction>
- struct pure_virtual_visitor
- : def_visitor<pure_virtual_visitor<PointerToMemberFunction> >
- {
- pure_virtual_visitor(PointerToMemberFunction pmf)
- : m_pmf(pmf)
- {}
-
- private:
- friend class python::def_visitor_access;
-
- template <class C_, class Options>
- void visit(C_& c, char const* name, Options& options) const
- {
- // This should probably be a nicer error message
- BOOST_STATIC_ASSERT(!Options::has_default_implementation);
- // Add the virtual function dispatcher
- c.def(
- name
- , m_pmf
- , options.doc()
- , options.keywords()
- , options.policies()
- );
- typedef BOOST_DEDUCED_TYPENAME C_::metadata::held_type held_type;
-
- // Add the default implementation which raises the exception
- c.def(
- name
- , make_function(
- detail::nullary_function_adaptor<void(*)()>(pure_virtual_called)
- , default_call_policies()
- , detail::error_signature<held_type>(detail::get_signature(m_pmf))
- )
- );
- }
-
- private: // data members
- PointerToMemberFunction m_pmf;
- };
- }
- //
- // Passed a pointer to member function, generates a def_visitor which
- // creates a method that only dispatches to Python if the function has
- // been overridden, either in C++ or in Python, raising a "pure
- // virtual called" exception otherwise.
- //
- template <class PointerToMemberFunction>
- detail::pure_virtual_visitor<PointerToMemberFunction>
- pure_virtual(PointerToMemberFunction pmf)
- {
- return detail::pure_virtual_visitor<PointerToMemberFunction>(pmf);
- }
- }} // namespace boost::python
- #endif // PURE_VIRTUAL_DWA2003810_HPP
|