1// Copyright David Abrahams 2003.
2// Distributed under the Boost Software License, Version 1.0. (See
3// accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5#ifndef PURE_VIRTUAL_DWA2003810_HPP
6# define PURE_VIRTUAL_DWA2003810_HPP
7
8# include <boost/python/def_visitor.hpp>
9# include <boost/python/default_call_policies.hpp>
10# include <boost/mpl/push_front.hpp>
11# include <boost/mpl/pop_front.hpp>
12
13# include <boost/python/detail/nullary_function_adaptor.hpp>
14
15namespace boost { namespace python {
16
17namespace detail
18{
19 //
20 // @group Helpers for pure_virtual_visitor. {
21 //
22
23 // Raises a Python RuntimeError reporting that a pure virtual
24 // function was called.
25 void BOOST_PYTHON_DECL pure_virtual_called();
26
27 // Replace the two front elements of S with T1 and T2
28 template <class S, class T1, class T2>
29 struct replace_front2
30 {
31 // Metafunction forwarding seemed to confound vc6
32 typedef typename mpl::push_front<
33 typename mpl::push_front<
34 typename mpl::pop_front<
35 typename mpl::pop_front<
36 S
37 >::type
38 >::type
39 , T2
40 >::type
41 , T1
42 >::type type;
43 };
44
45 // Given an MPL sequence representing a member function [object]
46 // signature, returns a new MPL sequence whose return type is
47 // replaced by void, and whose first argument is replaced by C&.
48 template <class C, class S>
49 typename replace_front2<S,void,C&>::type
50 error_signature(S)
51 {
52 typedef typename replace_front2<S,void,C&>::type r;
53 return r();
54 }
55
56 //
57 // }
58 //
59
60 //
61 // A def_visitor which defines a method as usual, then adds a
62 // corresponding function which raises a "pure virtual called"
63 // exception unless it's been overridden.
64 //
65 template <class PointerToMemberFunction>
66 struct pure_virtual_visitor
67 : def_visitor<pure_virtual_visitor<PointerToMemberFunction> >
68 {
69 pure_virtual_visitor(PointerToMemberFunction pmf)
70 : m_pmf(pmf)
71 {}
72
73 private:
74 friend class python::def_visitor_access;
75
76 template <class C_, class Options>
77 void visit(C_& c, char const* name, Options& options) const
78 {
79 // This should probably be a nicer error message
80 BOOST_STATIC_ASSERT(!Options::has_default_implementation);
81
82 // Add the virtual function dispatcher
83 c.def(
84 name
85 , m_pmf
86 , options.doc()
87 , options.keywords()
88 , options.policies()
89 );
90
91 typedef BOOST_DEDUCED_TYPENAME C_::metadata::held_type held_type;
92
93 // Add the default implementation which raises the exception
94 c.def(
95 name
96 , make_function(
97 detail::nullary_function_adaptor<void(*)()>(pure_virtual_called)
98 , default_call_policies()
99 , detail::error_signature<held_type>(detail::get_signature(m_pmf))
100 )
101 );
102 }
103
104 private: // data members
105 PointerToMemberFunction m_pmf;
106 };
107}
108
109//
110// Passed a pointer to member function, generates a def_visitor which
111// creates a method that only dispatches to Python if the function has
112// been overridden, either in C++ or in Python, raising a "pure
113// virtual called" exception otherwise.
114//
115template <class PointerToMemberFunction>
116detail::pure_virtual_visitor<PointerToMemberFunction>
117pure_virtual(PointerToMemberFunction pmf)
118{
119 return detail::pure_virtual_visitor<PointerToMemberFunction>(pmf);
120}
121
122}} // namespace boost::python
123
124#endif // PURE_VIRTUAL_DWA2003810_HPP
125

source code of boost/boost/python/pure_virtual.hpp