Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/python/object/class_metadata.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright David Abrahams 2004.
0002 // Copyright Stefan Seefeld 2016.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef boost_python_object_class_metadata_hpp_
0008 #define boost_python_object_class_metadata_hpp_
0009 
0010 #include <boost/python/converter/shared_ptr_from_python.hpp>
0011 #include <boost/python/object/inheritance.hpp>
0012 #include <boost/python/object/class_wrapper.hpp>
0013 #include <boost/python/object/make_instance.hpp>
0014 #include <boost/python/object/value_holder.hpp>
0015 #include <boost/python/object/pointer_holder.hpp>
0016 #include <boost/python/object/make_ptr_instance.hpp>
0017 
0018 #include <boost/python/detail/force_instantiate.hpp>
0019 #include <boost/python/detail/not_specified.hpp>
0020 #include <boost/python/detail/type_traits.hpp>
0021 
0022 #include <boost/python/has_back_reference.hpp>
0023 #include <boost/python/bases.hpp>
0024 
0025 #include <boost/mpl/if.hpp>
0026 #include <boost/mpl/eval_if.hpp>
0027 #include <boost/mpl/bool.hpp>
0028 #include <boost/mpl/or.hpp>
0029 #include <boost/mpl/identity.hpp>
0030 #include <boost/mpl/for_each.hpp>
0031 #include <boost/mpl/placeholders.hpp>
0032 #include <boost/mpl/single_view.hpp>
0033 
0034 #include <boost/mpl/assert.hpp>
0035 
0036 #include <boost/noncopyable.hpp>
0037 #include <boost/detail/workaround.hpp>
0038 
0039 namespace boost { namespace python { namespace objects { 
0040 
0041 BOOST_PYTHON_DECL
0042 void copy_class_object(type_info const& src, type_info const& dst);
0043 
0044 //
0045 // Support for registering base/derived relationships
0046 //
0047 template <class Derived>
0048 struct register_base_of
0049 {
0050     template <class Base>
0051     inline void operator()(Base*) const
0052     {
0053         BOOST_MPL_ASSERT_NOT((boost::python::detail::is_same<Base,Derived>));
0054         
0055         // Register the Base class
0056         register_dynamic_id<Base>();
0057 
0058         // Register the up-cast
0059         register_conversion<Derived,Base>(false);
0060 
0061         // Register the down-cast, if appropriate.
0062         this->register_downcast((Base*)0, boost::python::detail::is_polymorphic<Base>());
0063     }
0064 
0065  private:
0066     static inline void register_downcast(void*, boost::python::detail::false_) {}
0067     
0068     template <class Base>
0069     static inline void register_downcast(Base*, boost::python::detail::true_)
0070     {
0071         register_conversion<Base, Derived>(true);
0072     }
0073 
0074 };
0075 
0076 //
0077 // Preamble of register_class.  Also used for callback classes, which
0078 // need some registration of their own.
0079 //
0080 
0081 template <class T, class Bases>
0082 inline void register_shared_ptr_from_python_and_casts(T*, Bases)
0083 {
0084   // Constructor performs registration
0085   python::detail::force_instantiate(converter::shared_ptr_from_python<T, boost::shared_ptr>());
0086 #if !defined(BOOST_NO_CXX11_SMART_PTR)
0087   python::detail::force_instantiate(converter::shared_ptr_from_python<T, std::shared_ptr>());
0088 #endif
0089 
0090   //
0091   // register all up/downcasts here.  We're using the alternate
0092   // interface to mpl::for_each to avoid an MSVC 6 bug.
0093   //
0094   register_dynamic_id<T>();
0095   mpl::for_each(register_base_of<T>(), (Bases*)0, (boost::python::detail::add_pointer<mpl::_>*)0);
0096 }
0097 
0098 //
0099 // Helper for choosing the unnamed held_type argument
0100 //
0101 template <class T, class Prev>
0102 struct select_held_type
0103   : mpl::if_<
0104         mpl::or_<
0105             python::detail::specifies_bases<T>
0106           , boost::python::detail::is_same<T,noncopyable>
0107         >
0108       , Prev
0109       , T
0110     >
0111 {
0112 };
0113 
0114 template <
0115     class T // class being wrapped
0116   , class X1 // = detail::not_specified
0117   , class X2 // = detail::not_specified
0118   , class X3 // = detail::not_specified
0119 >
0120 struct class_metadata
0121 {
0122     //
0123     // Calculate the unnamed template arguments
0124     //
0125     
0126     // held_type_arg -- not_specified, [a class derived from] T or a
0127     // smart pointer to [a class derived from] T.  Preserving
0128     // not_specified allows us to give class_<T,T> a back-reference.
0129     typedef typename select_held_type<
0130         X1
0131       , typename select_held_type<
0132             X2
0133           , typename select_held_type<
0134                 X3
0135               , python::detail::not_specified
0136             >::type
0137         >::type
0138     >::type held_type_arg;
0139 
0140     // bases
0141     typedef typename python::detail::select_bases<
0142         X1
0143       , typename python::detail::select_bases<
0144             X2
0145           , typename python::detail::select_bases<
0146                 X3
0147               , python::bases<>
0148             >::type
0149         >::type
0150     >::type bases;
0151 
0152     typedef mpl::or_<
0153         boost::python::detail::is_same<X1,noncopyable>
0154       , boost::python::detail::is_same<X2,noncopyable>
0155       , boost::python::detail::is_same<X3,noncopyable>
0156     > is_noncopyable;
0157     
0158     //
0159     // Holder computation.
0160     //
0161     
0162     // Compute the actual type that will be held in the Holder.
0163     typedef typename mpl::if_<
0164         boost::python::detail::is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg
0165     >::type held_type;
0166 
0167     // Determine if the object will be held by value
0168     typedef mpl::bool_<boost::python::detail::is_convertible<held_type*,T*>::value> use_value_holder;
0169     
0170     // Compute the "wrapped type", that is, if held_type is a smart
0171     // pointer, we're talking about the pointee.
0172     typedef typename mpl::eval_if<
0173         use_value_holder
0174       , mpl::identity<held_type>
0175       , pointee<held_type>
0176     >::type wrapped;
0177 
0178     // Determine whether to use a "back-reference holder"
0179     typedef mpl::bool_<
0180         mpl::or_<
0181             has_back_reference<T>
0182           , boost::python::detail::is_same<held_type_arg,T>
0183           , is_base_and_derived<T,wrapped>
0184         >::value
0185     > use_back_reference;
0186 
0187     // Select the holder.
0188     typedef typename mpl::eval_if<
0189         use_back_reference
0190       , mpl::if_<
0191             use_value_holder
0192           , value_holder_back_reference<T, wrapped>
0193           , pointer_holder_back_reference<held_type,T>
0194         >
0195       , mpl::if_<
0196             use_value_holder
0197           , value_holder<T>
0198           , pointer_holder<held_type,wrapped>
0199         >
0200     >::type holder;
0201     
0202     inline static void register_() // Register the runtime metadata.
0203     {
0204         class_metadata::register_aux((T*)0);
0205     }
0206 
0207  private:
0208     template <class T2>
0209     inline static void register_aux(python::wrapper<T2>*) 
0210     {
0211         typedef typename mpl::not_<boost::python::detail::is_same<T2,wrapped> >::type use_callback;
0212         class_metadata::register_aux2((T2*)0, use_callback());
0213     }
0214 
0215     inline static void register_aux(void*) 
0216     {
0217         typedef typename is_base_and_derived<T,wrapped>::type use_callback;
0218         class_metadata::register_aux2((T*)0, use_callback());
0219     }
0220 
0221     template <class T2, class Callback>
0222     inline static void register_aux2(T2*, Callback) 
0223     {
0224     objects::register_shared_ptr_from_python_and_casts((T2*)0, bases());
0225         class_metadata::maybe_register_callback_class((T2*)0, Callback());
0226 
0227         class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable());
0228         
0229         class_metadata::maybe_register_pointer_to_python(
0230             (T2*)0, (use_value_holder*)0, (use_back_reference*)0);
0231     }
0232 
0233 
0234     //
0235     // Support for converting smart pointers to python
0236     //
0237     inline static void maybe_register_pointer_to_python(...) {}
0238 
0239 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
0240     inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*)
0241     {
0242         objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >());
0243         objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
0244     }
0245 #endif
0246 
0247     template <class T2>
0248     inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*)
0249     {
0250         python::detail::force_instantiate(
0251             objects::class_value_wrapper<
0252                 held_type
0253               , make_ptr_instance<T2, pointer_holder<held_type, T2> >
0254             >()
0255         );
0256 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
0257         // explicit qualification of type_id makes msvc6 happy
0258         objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
0259 #endif
0260     }
0261     //
0262     // Support for registering to-python converters
0263     //
0264     inline static void maybe_register_class_to_python(void*, mpl::true_) {}
0265     
0266 
0267     template <class T2>
0268     inline static void maybe_register_class_to_python(T2*, mpl::false_)
0269     {
0270         python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >());
0271 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
0272         // explicit qualification of type_id makes msvc6 happy
0273         objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
0274 #endif
0275     }
0276 
0277     //
0278     // Support for registering callback classes
0279     //
0280     inline static void maybe_register_callback_class(void*, mpl::false_) {}
0281 
0282     template <class T2>
0283     inline static void maybe_register_callback_class(T2*, mpl::true_)
0284     {
0285     objects::register_shared_ptr_from_python_and_casts(
0286             (wrapped*)0, mpl::single_view<T2>());
0287         // explicit qualification of type_id makes msvc6 happy
0288         objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>());
0289     }
0290 };
0291 
0292 }}} // namespace boost::python::object
0293 
0294 #endif