pure_virtual.hpp 3.6 KB

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