You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
124 lines
3.6 KiB
124 lines
3.6 KiB
// 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 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(C)) |
|
{ |
|
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
|
|
|