os/ossrv/ossrv_pub/boost_apis/boost/python/pure_virtual.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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
    50   error_signature(S BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(C))
    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 //
   115 template <class PointerToMemberFunction>
   116 detail::pure_virtual_visitor<PointerToMemberFunction>
   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