• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 namespace boost { namespace python {
16 
17 namespace 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
error_signature(S)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   {
pure_virtual_visitorboost::python::detail::pure_virtual_visitor69       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>
visitboost::python::detail::pure_virtual_visitor77       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 //
115 template <class PointerToMemberFunction>
116 detail::pure_virtual_visitor<PointerToMemberFunction>
pure_virtual(PointerToMemberFunction pmf)117 pure_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