sl@0: // Copyright David Abrahams 2002. sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: #ifndef INHERITANCE_DWA200216_HPP sl@0: # define INHERITANCE_DWA200216_HPP sl@0: sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: sl@0: namespace boost { namespace python { namespace objects { sl@0: sl@0: typedef type_info class_id; sl@0: using python::type_id; sl@0: sl@0: // Types used to get address and id of most derived type sl@0: typedef std::pair dynamic_id_t; sl@0: typedef dynamic_id_t (*dynamic_id_function)(void*); sl@0: sl@0: BOOST_PYTHON_DECL void register_dynamic_id_aux( sl@0: class_id static_id, dynamic_id_function get_dynamic_id); sl@0: sl@0: BOOST_PYTHON_DECL void add_cast( sl@0: class_id src_t, class_id dst_t, void* (*cast)(void*), bool is_downcast); sl@0: sl@0: // sl@0: // a generator with an execute() function which, given a source type sl@0: // and a pointer to an object of that type, returns its most-derived sl@0: // /reachable/ type identifier and object pointer. sl@0: // sl@0: sl@0: // first, the case where T has virtual functions sl@0: template sl@0: struct polymorphic_id_generator sl@0: { sl@0: static dynamic_id_t execute(void* p_) sl@0: { sl@0: T* p = static_cast(p_); sl@0: return std::make_pair(dynamic_cast(p), class_id(typeid(*p))); sl@0: } sl@0: }; sl@0: sl@0: // now, the non-polymorphic case. sl@0: template sl@0: struct non_polymorphic_id_generator sl@0: { sl@0: static dynamic_id_t execute(void* p_) sl@0: { sl@0: return std::make_pair(p_, python::type_id()); sl@0: } sl@0: }; sl@0: sl@0: // Now the generalized selector sl@0: template sl@0: struct dynamic_id_generator sl@0: : mpl::if_< sl@0: boost::is_polymorphic sl@0: , boost::python::objects::polymorphic_id_generator sl@0: , boost::python::objects::non_polymorphic_id_generator sl@0: > sl@0: {}; sl@0: sl@0: // Register the dynamic id function for T with the type-conversion sl@0: // system. sl@0: template sl@0: void register_dynamic_id(T* = 0) sl@0: { sl@0: typedef typename dynamic_id_generator::type generator; sl@0: register_dynamic_id_aux( sl@0: python::type_id(), &generator::execute); sl@0: } sl@0: sl@0: // sl@0: // a generator with an execute() function which, given a void* sl@0: // pointing to an object of type Source will attempt to convert it to sl@0: // an object of type Target. sl@0: // sl@0: sl@0: template sl@0: struct dynamic_cast_generator sl@0: { sl@0: static void* execute(void* source) sl@0: { sl@0: return dynamic_cast( sl@0: static_cast(source)); sl@0: } sl@0: sl@0: }; sl@0: sl@0: template sl@0: struct implicit_cast_generator sl@0: { sl@0: static void* execute(void* source) sl@0: { sl@0: Target* result = static_cast(source); sl@0: return result; sl@0: } sl@0: }; sl@0: sl@0: template sl@0: struct cast_generator sl@0: : mpl::if_< sl@0: is_base_and_derived sl@0: , implicit_cast_generator sl@0: , dynamic_cast_generator sl@0: > sl@0: { sl@0: }; sl@0: sl@0: template sl@0: inline void register_conversion( sl@0: bool is_downcast = ::boost::is_base_and_derived::value sl@0: // These parameters shouldn't be used; they're an MSVC bug workaround sl@0: , Source* = 0, Target* = 0) sl@0: { sl@0: typedef typename cast_generator::type generator; sl@0: sl@0: add_cast( sl@0: python::type_id() sl@0: , python::type_id() sl@0: , &generator::execute sl@0: , is_downcast sl@0: ); sl@0: } sl@0: sl@0: }}} // namespace boost::python::object sl@0: sl@0: #endif // INHERITANCE_DWA200216_HPP