summaryrefslogtreecommitdiff
path: root/boost/python/pure_virtual.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/python/pure_virtual.hpp')
-rw-r--r--boost/python/pure_virtual.hpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/boost/python/pure_virtual.hpp b/boost/python/pure_virtual.hpp
new file mode 100644
index 0000000000..b3b34ffcdb
--- /dev/null
+++ b/boost/python/pure_virtual.hpp
@@ -0,0 +1,124 @@
+// 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