Chris@16: // Copyright David Abrahams 2004. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef CLASS_METADATA_DWA2004719_HPP Chris@16: # define CLASS_METADATA_DWA2004719_HPP Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: Chris@16: namespace boost { namespace python { namespace objects { Chris@16: Chris@16: BOOST_PYTHON_DECL Chris@16: void copy_class_object(type_info const& src, type_info const& dst); Chris@16: Chris@16: // Chris@16: // Support for registering base/derived relationships Chris@16: // Chris@16: template Chris@16: struct register_base_of Chris@16: { Chris@16: template Chris@16: inline void operator()(Base*) const Chris@16: { Chris@16: # if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) Chris@16: BOOST_MPL_ASSERT_NOT((is_same)); Chris@16: # else Chris@16: BOOST_STATIC_ASSERT(!(is_same::value)); Chris@16: # endif Chris@16: Chris@16: // Register the Base class Chris@16: register_dynamic_id(); Chris@16: Chris@16: // Register the up-cast Chris@16: register_conversion(false); Chris@16: Chris@16: // Register the down-cast, if appropriate. Chris@16: this->register_downcast((Base*)0, is_polymorphic()); Chris@16: } Chris@16: Chris@16: private: Chris@16: static inline void register_downcast(void*, mpl::false_) {} Chris@16: Chris@16: template Chris@16: static inline void register_downcast(Base*, mpl::true_) Chris@16: { Chris@16: register_conversion(true); Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: // Chris@16: // Preamble of register_class. Also used for callback classes, which Chris@16: // need some registration of their own. Chris@16: // Chris@16: template Chris@16: inline void register_shared_ptr_from_python_and_casts(T*, Bases) Chris@16: { Chris@16: // Constructor performs registration Chris@16: python::detail::force_instantiate(converter::shared_ptr_from_python()); Chris@16: Chris@16: // Chris@16: // register all up/downcasts here. We're using the alternate Chris@16: // interface to mpl::for_each to avoid an MSVC 6 bug. Chris@16: // Chris@16: register_dynamic_id(); Chris@16: mpl::for_each(register_base_of(), (Bases*)0, (add_pointer*)0); Chris@16: } Chris@16: Chris@16: // Chris@16: // Helper for choosing the unnamed held_type argument Chris@16: // Chris@16: template Chris@16: struct select_held_type Chris@16: : mpl::if_< Chris@16: mpl::or_< Chris@16: python::detail::specifies_bases Chris@16: , is_same Chris@16: > Chris@16: , Prev Chris@16: , T Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: template < Chris@16: class T // class being wrapped Chris@16: , class X1 // = detail::not_specified Chris@16: , class X2 // = detail::not_specified Chris@16: , class X3 // = detail::not_specified Chris@16: > Chris@16: struct class_metadata Chris@16: { Chris@16: // Chris@16: // Calculate the unnamed template arguments Chris@16: // Chris@16: Chris@16: // held_type_arg -- not_specified, [a class derived from] T or a Chris@16: // smart pointer to [a class derived from] T. Preserving Chris@16: // not_specified allows us to give class_ a back-reference. Chris@16: typedef typename select_held_type< Chris@16: X1 Chris@16: , typename select_held_type< Chris@16: X2 Chris@16: , typename select_held_type< Chris@16: X3 Chris@16: , python::detail::not_specified Chris@16: >::type Chris@16: >::type Chris@16: >::type held_type_arg; Chris@16: Chris@16: // bases Chris@16: typedef typename python::detail::select_bases< Chris@16: X1 Chris@16: , typename python::detail::select_bases< Chris@16: X2 Chris@16: , typename python::detail::select_bases< Chris@16: X3 Chris@16: , python::bases<> Chris@16: >::type Chris@16: >::type Chris@16: >::type bases; Chris@16: Chris@16: typedef mpl::or_< Chris@16: is_same Chris@16: , is_same Chris@16: , is_same Chris@16: > is_noncopyable; Chris@16: Chris@16: // Chris@16: // Holder computation. Chris@16: // Chris@16: Chris@16: // Compute the actual type that will be held in the Holder. Chris@16: typedef typename mpl::if_< Chris@16: is_same, T, held_type_arg Chris@16: >::type held_type; Chris@16: Chris@16: // Determine if the object will be held by value Chris@16: typedef is_convertible use_value_holder; Chris@16: Chris@16: // Compute the "wrapped type", that is, if held_type is a smart Chris@16: // pointer, we're talking about the pointee. Chris@16: typedef typename mpl::eval_if< Chris@16: use_value_holder Chris@16: , mpl::identity Chris@16: , pointee Chris@16: >::type wrapped; Chris@16: Chris@16: // Determine whether to use a "back-reference holder" Chris@16: typedef mpl::or_< Chris@16: has_back_reference Chris@16: , is_same Chris@16: , is_base_and_derived Chris@16: > use_back_reference; Chris@16: Chris@16: // Select the holder. Chris@16: typedef typename mpl::eval_if< Chris@16: use_back_reference Chris@16: , mpl::if_< Chris@16: use_value_holder Chris@16: , value_holder_back_reference Chris@16: , pointer_holder_back_reference Chris@16: > Chris@16: , mpl::if_< Chris@16: use_value_holder Chris@16: , value_holder Chris@16: , pointer_holder Chris@16: > Chris@16: >::type holder; Chris@16: Chris@16: inline static void register_() // Register the runtime metadata. Chris@16: { Chris@16: class_metadata::register_aux((T*)0); Chris@16: } Chris@16: Chris@16: private: Chris@16: template Chris@16: inline static void register_aux(python::wrapper*) Chris@16: { Chris@16: typedef typename mpl::not_ >::type use_callback; Chris@16: class_metadata::register_aux2((T2*)0, use_callback()); Chris@16: } Chris@16: Chris@16: inline static void register_aux(void*) Chris@16: { Chris@16: typedef typename is_base_and_derived::type use_callback; Chris@16: class_metadata::register_aux2((T*)0, use_callback()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline static void register_aux2(T2*, Callback) Chris@16: { Chris@16: objects::register_shared_ptr_from_python_and_casts((T2*)0, bases()); Chris@16: Chris@16: class_metadata::maybe_register_callback_class((T2*)0, Callback()); Chris@16: Chris@16: class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable()); Chris@16: Chris@16: class_metadata::maybe_register_pointer_to_python( Chris@16: (T2*)0, (use_value_holder*)0, (use_back_reference*)0); Chris@16: } Chris@16: Chris@16: Chris@16: // Chris@16: // Support for converting smart pointers to python Chris@16: // Chris@16: inline static void maybe_register_pointer_to_python(...) {} Chris@16: Chris@16: #ifndef BOOST_PYTHON_NO_PY_SIGNATURES Chris@16: inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*) Chris@16: { Chris@16: objects::copy_class_object(python::type_id(), python::type_id >()); Chris@16: objects::copy_class_object(python::type_id(), python::type_id >()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*) Chris@16: { Chris@16: python::detail::force_instantiate( Chris@16: objects::class_value_wrapper< Chris@16: held_type Chris@16: , make_ptr_instance > Chris@16: >() Chris@16: ); Chris@16: #ifndef BOOST_PYTHON_NO_PY_SIGNATURES Chris@16: // explicit qualification of type_id makes msvc6 happy Chris@16: objects::copy_class_object(python::type_id(), python::type_id()); Chris@16: #endif Chris@16: } Chris@16: // Chris@16: // Support for registering to-python converters Chris@16: // Chris@16: inline static void maybe_register_class_to_python(void*, mpl::true_) {} Chris@16: Chris@16: Chris@16: template Chris@16: inline static void maybe_register_class_to_python(T2*, mpl::false_) Chris@16: { Chris@16: python::detail::force_instantiate(class_cref_wrapper >()); Chris@16: #ifndef BOOST_PYTHON_NO_PY_SIGNATURES Chris@16: // explicit qualification of type_id makes msvc6 happy Chris@16: objects::copy_class_object(python::type_id(), python::type_id()); Chris@16: #endif Chris@16: } Chris@16: Chris@16: // Chris@16: // Support for registering callback classes Chris@16: // Chris@16: inline static void maybe_register_callback_class(void*, mpl::false_) {} Chris@16: Chris@16: template Chris@16: inline static void maybe_register_callback_class(T2*, mpl::true_) Chris@16: { Chris@16: objects::register_shared_ptr_from_python_and_casts( Chris@16: (wrapped*)0, mpl::single_view()); Chris@16: Chris@16: // explicit qualification of type_id makes msvc6 happy Chris@16: objects::copy_class_object(python::type_id(), python::type_id()); Chris@16: } Chris@16: }; Chris@16: Chris@16: }}} // namespace boost::python::object Chris@16: Chris@16: #endif // CLASS_METADATA_DWA2004719_HPP