annotate DEPENDENCIES/generic/include/boost/python/converter/object_manager.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright David Abrahams 2002.
Chris@16 2 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 3 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 4 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5 #ifndef OBJECT_MANAGER_DWA2002614_HPP
Chris@16 6 # define OBJECT_MANAGER_DWA2002614_HPP
Chris@16 7
Chris@16 8 # include <boost/python/handle.hpp>
Chris@16 9 # include <boost/python/cast.hpp>
Chris@16 10 # include <boost/python/converter/pyobject_traits.hpp>
Chris@16 11 # include <boost/type_traits/object_traits.hpp>
Chris@16 12 # include <boost/mpl/if.hpp>
Chris@16 13 # include <boost/python/detail/indirect_traits.hpp>
Chris@16 14 # include <boost/mpl/bool.hpp>
Chris@16 15
Chris@16 16 // Facilities for dealing with types which always manage Python
Chris@16 17 // objects. Some examples are object, list, str, et. al. Different
Chris@16 18 // to_python/from_python conversion rules apply here because in
Chris@16 19 // contrast to other types which are typically embedded inside a
Chris@16 20 // Python object, these are wrapped around a Python object. For most
Chris@16 21 // object managers T, a C++ non-const T reference argument does not
Chris@16 22 // imply the existence of a T lvalue embedded in the corresponding
Chris@16 23 // Python argument, since mutating member functions on T actually only
Chris@16 24 // modify the held Python object.
Chris@16 25 //
Chris@16 26 // handle<T> is an object manager, though strictly speaking it should
Chris@16 27 // not be. In other words, even though mutating member functions of
Chris@16 28 // hanlde<T> actually modify the handle<T> and not the T object,
Chris@16 29 // handle<T>& arguments of wrapped functions will bind to "rvalues"
Chris@16 30 // wrapping the actual Python argument, just as with other object
Chris@16 31 // manager classes. Making an exception for handle<T> is simply not
Chris@16 32 // worth the trouble.
Chris@16 33 //
Chris@16 34 // borrowed<T> cv* is an object manager so that we can use the general
Chris@16 35 // to_python mechanisms to convert raw Python object pointers to
Chris@16 36 // python, without the usual semantic problems of using raw pointers.
Chris@16 37
Chris@16 38
Chris@16 39 // Object Manager Concept requirements:
Chris@16 40 //
Chris@16 41 // T is an Object Manager
Chris@16 42 // p is a PyObject*
Chris@16 43 // x is a T
Chris@16 44 //
Chris@16 45 // * object_manager_traits<T>::is_specialized == true
Chris@16 46 //
Chris@16 47 // * T(detail::borrowed_reference(p))
Chris@16 48 // Manages p without checking its type
Chris@16 49 //
Chris@16 50 // * get_managed_object(x, boost::python::tag)
Chris@16 51 // Convertible to PyObject*
Chris@16 52 //
Chris@16 53 // Additional requirements if T can be converted from_python:
Chris@16 54 //
Chris@16 55 // * T(object_manager_traits<T>::adopt(p))
Chris@16 56 // steals a reference to p, or throws a TypeError exception if
Chris@16 57 // p doesn't have an appropriate type. May assume p is non-null
Chris@16 58 //
Chris@16 59 // * X::check(p)
Chris@16 60 // convertible to bool. True iff T(X::construct(p)) will not
Chris@16 61 // throw.
Chris@16 62
Chris@16 63 // Forward declarations
Chris@16 64 //
Chris@16 65 namespace boost { namespace python
Chris@16 66 {
Chris@16 67 namespace api
Chris@16 68 {
Chris@16 69 class object;
Chris@16 70 }
Chris@16 71 }}
Chris@16 72
Chris@16 73 namespace boost { namespace python { namespace converter {
Chris@16 74
Chris@16 75
Chris@16 76 // Specializations for handle<T>
Chris@16 77 template <class T>
Chris@16 78 struct handle_object_manager_traits
Chris@16 79 : pyobject_traits<typename T::element_type>
Chris@16 80 {
Chris@16 81 private:
Chris@16 82 typedef pyobject_traits<typename T::element_type> base;
Chris@16 83
Chris@16 84 public:
Chris@16 85 BOOST_STATIC_CONSTANT(bool, is_specialized = true);
Chris@16 86
Chris@16 87 // Initialize with a null_ok pointer for efficiency, bypassing the
Chris@16 88 // null check since the source is always non-null.
Chris@16 89 static null_ok<typename T::element_type>* adopt(PyObject* p)
Chris@16 90 {
Chris@16 91 return python::allow_null(base::checked_downcast(p));
Chris@16 92 }
Chris@16 93 };
Chris@16 94
Chris@16 95 template <class T>
Chris@16 96 struct default_object_manager_traits
Chris@16 97 {
Chris@16 98 BOOST_STATIC_CONSTANT(
Chris@16 99 bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
Chris@16 100 );
Chris@16 101 };
Chris@16 102
Chris@16 103 template <class T>
Chris@16 104 struct object_manager_traits
Chris@16 105 : mpl::if_c<
Chris@16 106 is_handle<T>::value
Chris@16 107 , handle_object_manager_traits<T>
Chris@16 108 , default_object_manager_traits<T>
Chris@16 109 >::type
Chris@16 110 {
Chris@16 111 };
Chris@16 112
Chris@16 113 //
Chris@16 114 // Traits for detecting whether a type is an object manager or a
Chris@16 115 // (cv-qualified) reference to an object manager.
Chris@16 116 //
Chris@16 117
Chris@16 118 template <class T>
Chris@16 119 struct is_object_manager
Chris@16 120 : mpl::bool_<object_manager_traits<T>::is_specialized>
Chris@16 121 {
Chris@16 122 };
Chris@16 123
Chris@16 124 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
Chris@16 125 template <class T>
Chris@16 126 struct is_reference_to_object_manager
Chris@16 127 : mpl::false_
Chris@16 128 {
Chris@16 129 };
Chris@16 130
Chris@16 131 template <class T>
Chris@16 132 struct is_reference_to_object_manager<T&>
Chris@16 133 : is_object_manager<T>
Chris@16 134 {
Chris@16 135 };
Chris@16 136
Chris@16 137 template <class T>
Chris@16 138 struct is_reference_to_object_manager<T const&>
Chris@16 139 : is_object_manager<T>
Chris@16 140 {
Chris@16 141 };
Chris@16 142
Chris@16 143 template <class T>
Chris@16 144 struct is_reference_to_object_manager<T volatile&>
Chris@16 145 : is_object_manager<T>
Chris@16 146 {
Chris@16 147 };
Chris@16 148
Chris@16 149 template <class T>
Chris@16 150 struct is_reference_to_object_manager<T const volatile&>
Chris@16 151 : is_object_manager<T>
Chris@16 152 {
Chris@16 153 };
Chris@16 154 # else
Chris@16 155
Chris@16 156 namespace detail
Chris@16 157 {
Chris@16 158 typedef char (&yes_reference_to_object_manager)[1];
Chris@16 159 typedef char (&no_reference_to_object_manager)[2];
Chris@16 160
Chris@16 161 // A number of nastinesses go on here in order to work around MSVC6
Chris@16 162 // bugs.
Chris@16 163 template <class T>
Chris@16 164 struct is_object_manager_help
Chris@16 165 {
Chris@16 166 typedef typename mpl::if_<
Chris@16 167 is_object_manager<T>
Chris@16 168 , yes_reference_to_object_manager
Chris@16 169 , no_reference_to_object_manager
Chris@16 170 >::type type;
Chris@16 171
Chris@16 172 // If we just use the type instead of the result of calling this
Chris@16 173 // function, VC6 will ICE.
Chris@16 174 static type call();
Chris@16 175 };
Chris@16 176
Chris@16 177 // A set of overloads for each cv-qualification. The same argument
Chris@16 178 // is passed twice: the first one is used to unwind the cv*, and the
Chris@16 179 // second one is used to avoid relying on partial ordering for
Chris@16 180 // overload resolution.
Chris@16 181 template <class U>
Chris@16 182 typename is_object_manager_help<U>
Chris@16 183 is_object_manager_helper(U*, void*);
Chris@16 184
Chris@16 185 template <class U>
Chris@16 186 typename is_object_manager_help<U>
Chris@16 187 is_object_manager_helper(U const*, void const*);
Chris@16 188
Chris@16 189 template <class U>
Chris@16 190 typename is_object_manager_help<U>
Chris@16 191 is_object_manager_helper(U volatile*, void volatile*);
Chris@16 192
Chris@16 193 template <class U>
Chris@16 194 typename is_object_manager_help<U>
Chris@16 195 is_object_manager_helper(U const volatile*, void const volatile*);
Chris@16 196
Chris@16 197 template <class T>
Chris@16 198 struct is_reference_to_object_manager_nonref
Chris@16 199 : mpl::false_
Chris@16 200 {
Chris@16 201 };
Chris@16 202
Chris@16 203 template <class T>
Chris@16 204 struct is_reference_to_object_manager_ref
Chris@16 205 {
Chris@16 206 static T sample_object;
Chris@16 207 BOOST_STATIC_CONSTANT(
Chris@16 208 bool, value
Chris@16 209 = (sizeof(is_object_manager_helper(&sample_object, &sample_object).call())
Chris@16 210 == sizeof(detail::yes_reference_to_object_manager)
Chris@16 211 )
Chris@16 212 );
Chris@16 213 typedef mpl::bool_<value> type;
Chris@16 214 };
Chris@16 215 }
Chris@16 216
Chris@16 217 template <class T>
Chris@16 218 struct is_reference_to_object_manager
Chris@16 219 : mpl::if_<
Chris@16 220 is_reference<T>
Chris@16 221 , detail::is_reference_to_object_manager_ref<T>
Chris@16 222 , detail::is_reference_to_object_manager_nonref<T>
Chris@16 223 >::type
Chris@16 224 {
Chris@16 225 };
Chris@16 226 # endif
Chris@16 227
Chris@16 228 }}} // namespace boost::python::converter
Chris@16 229
Chris@16 230 #endif // OBJECT_MANAGER_DWA2002614_HPP