annotate DEPENDENCIES/generic/include/boost/python/object/class_metadata.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright David Abrahams 2004. Distributed under the Boost
Chris@16 2 // Software License, Version 1.0. (See accompanying
Chris@16 3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 4 #ifndef CLASS_METADATA_DWA2004719_HPP
Chris@16 5 # define CLASS_METADATA_DWA2004719_HPP
Chris@16 6 # include <boost/python/converter/shared_ptr_from_python.hpp>
Chris@16 7
Chris@16 8 # include <boost/python/object/inheritance.hpp>
Chris@16 9 # include <boost/python/object/class_wrapper.hpp>
Chris@16 10 # include <boost/python/object/make_instance.hpp>
Chris@16 11 # include <boost/python/object/value_holder.hpp>
Chris@16 12 # include <boost/python/object/pointer_holder.hpp>
Chris@16 13 # include <boost/python/object/make_ptr_instance.hpp>
Chris@16 14
Chris@16 15 # include <boost/python/detail/force_instantiate.hpp>
Chris@16 16 # include <boost/python/detail/not_specified.hpp>
Chris@16 17
Chris@16 18 # include <boost/python/has_back_reference.hpp>
Chris@16 19 # include <boost/python/bases.hpp>
Chris@16 20
Chris@16 21 # include <boost/type_traits/add_pointer.hpp>
Chris@16 22 # include <boost/type_traits/is_convertible.hpp>
Chris@16 23 # include <boost/type_traits/is_polymorphic.hpp>
Chris@16 24
Chris@16 25 # include <boost/mpl/if.hpp>
Chris@16 26 # include <boost/mpl/eval_if.hpp>
Chris@16 27 # include <boost/mpl/bool.hpp>
Chris@16 28 # include <boost/mpl/or.hpp>
Chris@16 29 # include <boost/mpl/identity.hpp>
Chris@16 30 # include <boost/mpl/for_each.hpp>
Chris@16 31 # include <boost/mpl/placeholders.hpp>
Chris@16 32 # include <boost/mpl/single_view.hpp>
Chris@16 33
Chris@16 34 # include <boost/mpl/assert.hpp>
Chris@16 35 # include <boost/type_traits/is_same.hpp>
Chris@16 36
Chris@16 37 # include <boost/type_traits/is_convertible.hpp>
Chris@16 38
Chris@16 39 # include <boost/noncopyable.hpp>
Chris@16 40 # include <boost/detail/workaround.hpp>
Chris@16 41
Chris@16 42 namespace boost { namespace python { namespace objects {
Chris@16 43
Chris@16 44 BOOST_PYTHON_DECL
Chris@16 45 void copy_class_object(type_info const& src, type_info const& dst);
Chris@16 46
Chris@16 47 //
Chris@16 48 // Support for registering base/derived relationships
Chris@16 49 //
Chris@16 50 template <class Derived>
Chris@16 51 struct register_base_of
Chris@16 52 {
Chris@16 53 template <class Base>
Chris@16 54 inline void operator()(Base*) const
Chris@16 55 {
Chris@16 56 # if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
Chris@16 57 BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
Chris@16 58 # else
Chris@16 59 BOOST_STATIC_ASSERT(!(is_same<Base,Derived>::value));
Chris@16 60 # endif
Chris@16 61
Chris@16 62 // Register the Base class
Chris@16 63 register_dynamic_id<Base>();
Chris@16 64
Chris@16 65 // Register the up-cast
Chris@16 66 register_conversion<Derived,Base>(false);
Chris@16 67
Chris@16 68 // Register the down-cast, if appropriate.
Chris@16 69 this->register_downcast((Base*)0, is_polymorphic<Base>());
Chris@16 70 }
Chris@16 71
Chris@16 72 private:
Chris@16 73 static inline void register_downcast(void*, mpl::false_) {}
Chris@16 74
Chris@16 75 template <class Base>
Chris@16 76 static inline void register_downcast(Base*, mpl::true_)
Chris@16 77 {
Chris@16 78 register_conversion<Base, Derived>(true);
Chris@16 79 }
Chris@16 80
Chris@16 81 };
Chris@16 82
Chris@16 83 //
Chris@16 84 // Preamble of register_class. Also used for callback classes, which
Chris@16 85 // need some registration of their own.
Chris@16 86 //
Chris@16 87 template <class T, class Bases>
Chris@16 88 inline void register_shared_ptr_from_python_and_casts(T*, Bases)
Chris@16 89 {
Chris@16 90 // Constructor performs registration
Chris@16 91 python::detail::force_instantiate(converter::shared_ptr_from_python<T>());
Chris@16 92
Chris@16 93 //
Chris@16 94 // register all up/downcasts here. We're using the alternate
Chris@16 95 // interface to mpl::for_each to avoid an MSVC 6 bug.
Chris@16 96 //
Chris@16 97 register_dynamic_id<T>();
Chris@16 98 mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0);
Chris@16 99 }
Chris@16 100
Chris@16 101 //
Chris@16 102 // Helper for choosing the unnamed held_type argument
Chris@16 103 //
Chris@16 104 template <class T, class Prev>
Chris@16 105 struct select_held_type
Chris@16 106 : mpl::if_<
Chris@16 107 mpl::or_<
Chris@16 108 python::detail::specifies_bases<T>
Chris@16 109 , is_same<T,noncopyable>
Chris@16 110 >
Chris@16 111 , Prev
Chris@16 112 , T
Chris@16 113 >
Chris@16 114 {
Chris@16 115 };
Chris@16 116
Chris@16 117 template <
Chris@16 118 class T // class being wrapped
Chris@16 119 , class X1 // = detail::not_specified
Chris@16 120 , class X2 // = detail::not_specified
Chris@16 121 , class X3 // = detail::not_specified
Chris@16 122 >
Chris@16 123 struct class_metadata
Chris@16 124 {
Chris@16 125 //
Chris@16 126 // Calculate the unnamed template arguments
Chris@16 127 //
Chris@16 128
Chris@16 129 // held_type_arg -- not_specified, [a class derived from] T or a
Chris@16 130 // smart pointer to [a class derived from] T. Preserving
Chris@16 131 // not_specified allows us to give class_<T,T> a back-reference.
Chris@16 132 typedef typename select_held_type<
Chris@16 133 X1
Chris@16 134 , typename select_held_type<
Chris@16 135 X2
Chris@16 136 , typename select_held_type<
Chris@16 137 X3
Chris@16 138 , python::detail::not_specified
Chris@16 139 >::type
Chris@16 140 >::type
Chris@16 141 >::type held_type_arg;
Chris@16 142
Chris@16 143 // bases
Chris@16 144 typedef typename python::detail::select_bases<
Chris@16 145 X1
Chris@16 146 , typename python::detail::select_bases<
Chris@16 147 X2
Chris@16 148 , typename python::detail::select_bases<
Chris@16 149 X3
Chris@16 150 , python::bases<>
Chris@16 151 >::type
Chris@16 152 >::type
Chris@16 153 >::type bases;
Chris@16 154
Chris@16 155 typedef mpl::or_<
Chris@16 156 is_same<X1,noncopyable>
Chris@16 157 , is_same<X2,noncopyable>
Chris@16 158 , is_same<X3,noncopyable>
Chris@16 159 > is_noncopyable;
Chris@16 160
Chris@16 161 //
Chris@16 162 // Holder computation.
Chris@16 163 //
Chris@16 164
Chris@16 165 // Compute the actual type that will be held in the Holder.
Chris@16 166 typedef typename mpl::if_<
Chris@16 167 is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg
Chris@16 168 >::type held_type;
Chris@16 169
Chris@16 170 // Determine if the object will be held by value
Chris@16 171 typedef is_convertible<held_type*,T*> use_value_holder;
Chris@16 172
Chris@16 173 // Compute the "wrapped type", that is, if held_type is a smart
Chris@16 174 // pointer, we're talking about the pointee.
Chris@16 175 typedef typename mpl::eval_if<
Chris@16 176 use_value_holder
Chris@16 177 , mpl::identity<held_type>
Chris@16 178 , pointee<held_type>
Chris@16 179 >::type wrapped;
Chris@16 180
Chris@16 181 // Determine whether to use a "back-reference holder"
Chris@16 182 typedef mpl::or_<
Chris@16 183 has_back_reference<T>
Chris@16 184 , is_same<held_type_arg,T>
Chris@16 185 , is_base_and_derived<T,wrapped>
Chris@16 186 > use_back_reference;
Chris@16 187
Chris@16 188 // Select the holder.
Chris@16 189 typedef typename mpl::eval_if<
Chris@16 190 use_back_reference
Chris@16 191 , mpl::if_<
Chris@16 192 use_value_holder
Chris@16 193 , value_holder_back_reference<T, wrapped>
Chris@16 194 , pointer_holder_back_reference<held_type,T>
Chris@16 195 >
Chris@16 196 , mpl::if_<
Chris@16 197 use_value_holder
Chris@16 198 , value_holder<T>
Chris@16 199 , pointer_holder<held_type,wrapped>
Chris@16 200 >
Chris@16 201 >::type holder;
Chris@16 202
Chris@16 203 inline static void register_() // Register the runtime metadata.
Chris@16 204 {
Chris@16 205 class_metadata::register_aux((T*)0);
Chris@16 206 }
Chris@16 207
Chris@16 208 private:
Chris@16 209 template <class T2>
Chris@16 210 inline static void register_aux(python::wrapper<T2>*)
Chris@16 211 {
Chris@16 212 typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback;
Chris@16 213 class_metadata::register_aux2((T2*)0, use_callback());
Chris@16 214 }
Chris@16 215
Chris@16 216 inline static void register_aux(void*)
Chris@16 217 {
Chris@16 218 typedef typename is_base_and_derived<T,wrapped>::type use_callback;
Chris@16 219 class_metadata::register_aux2((T*)0, use_callback());
Chris@16 220 }
Chris@16 221
Chris@16 222 template <class T2, class Callback>
Chris@16 223 inline static void register_aux2(T2*, Callback)
Chris@16 224 {
Chris@16 225 objects::register_shared_ptr_from_python_and_casts((T2*)0, bases());
Chris@16 226
Chris@16 227 class_metadata::maybe_register_callback_class((T2*)0, Callback());
Chris@16 228
Chris@16 229 class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable());
Chris@16 230
Chris@16 231 class_metadata::maybe_register_pointer_to_python(
Chris@16 232 (T2*)0, (use_value_holder*)0, (use_back_reference*)0);
Chris@16 233 }
Chris@16 234
Chris@16 235
Chris@16 236 //
Chris@16 237 // Support for converting smart pointers to python
Chris@16 238 //
Chris@16 239 inline static void maybe_register_pointer_to_python(...) {}
Chris@16 240
Chris@16 241 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
Chris@16 242 inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*)
Chris@16 243 {
Chris@16 244 objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >());
Chris@16 245 objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
Chris@16 246 }
Chris@16 247 #endif
Chris@16 248
Chris@16 249 template <class T2>
Chris@16 250 inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*)
Chris@16 251 {
Chris@16 252 python::detail::force_instantiate(
Chris@16 253 objects::class_value_wrapper<
Chris@16 254 held_type
Chris@16 255 , make_ptr_instance<T2, pointer_holder<held_type, T2> >
Chris@16 256 >()
Chris@16 257 );
Chris@16 258 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
Chris@16 259 // explicit qualification of type_id makes msvc6 happy
Chris@16 260 objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
Chris@16 261 #endif
Chris@16 262 }
Chris@16 263 //
Chris@16 264 // Support for registering to-python converters
Chris@16 265 //
Chris@16 266 inline static void maybe_register_class_to_python(void*, mpl::true_) {}
Chris@16 267
Chris@16 268
Chris@16 269 template <class T2>
Chris@16 270 inline static void maybe_register_class_to_python(T2*, mpl::false_)
Chris@16 271 {
Chris@16 272 python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >());
Chris@16 273 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
Chris@16 274 // explicit qualification of type_id makes msvc6 happy
Chris@16 275 objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
Chris@16 276 #endif
Chris@16 277 }
Chris@16 278
Chris@16 279 //
Chris@16 280 // Support for registering callback classes
Chris@16 281 //
Chris@16 282 inline static void maybe_register_callback_class(void*, mpl::false_) {}
Chris@16 283
Chris@16 284 template <class T2>
Chris@16 285 inline static void maybe_register_callback_class(T2*, mpl::true_)
Chris@16 286 {
Chris@16 287 objects::register_shared_ptr_from_python_and_casts(
Chris@16 288 (wrapped*)0, mpl::single_view<T2>());
Chris@16 289
Chris@16 290 // explicit qualification of type_id makes msvc6 happy
Chris@16 291 objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>());
Chris@16 292 }
Chris@16 293 };
Chris@16 294
Chris@16 295 }}} // namespace boost::python::object
Chris@16 296
Chris@16 297 #endif // CLASS_METADATA_DWA2004719_HPP