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