Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:37

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef OBJECT_MANAGER_DWA2002614_HPP
0006 # define OBJECT_MANAGER_DWA2002614_HPP
0007 
0008 # include <boost/python/handle.hpp>
0009 # include <boost/python/cast.hpp>
0010 # include <boost/python/converter/pyobject_traits.hpp>
0011 # include <boost/python/detail/type_traits.hpp>
0012 # include <boost/mpl/if.hpp>
0013 # include <boost/python/detail/indirect_traits.hpp>
0014 # include <boost/mpl/bool.hpp>
0015 
0016 // Facilities for dealing with types which always manage Python
0017 // objects. Some examples are object, list, str, et. al. Different
0018 // to_python/from_python conversion rules apply here because in
0019 // contrast to other types which are typically embedded inside a
0020 // Python object, these are wrapped around a Python object. For most
0021 // object managers T, a C++ non-const T reference argument does not
0022 // imply the existence of a T lvalue embedded in the corresponding
0023 // Python argument, since mutating member functions on T actually only
0024 // modify the held Python object.
0025 //
0026 // handle<T> is an object manager, though strictly speaking it should
0027 // not be. In other words, even though mutating member functions of
0028 // hanlde<T> actually modify the handle<T> and not the T object,
0029 // handle<T>& arguments of wrapped functions will bind to "rvalues"
0030 // wrapping the actual Python argument, just as with other object
0031 // manager classes. Making an exception for handle<T> is simply not
0032 // worth the trouble.
0033 //
0034 // borrowed<T> cv* is an object manager so that we can use the general
0035 // to_python mechanisms to convert raw Python object pointers to
0036 // python, without the usual semantic problems of using raw pointers.
0037 
0038 
0039 // Object Manager Concept requirements:
0040 //
0041 //    T is an Object Manager
0042 //    p is a PyObject*
0043 //    x is a T
0044 //
0045 //    * object_manager_traits<T>::is_specialized == true
0046 //
0047 //    * T(detail::borrowed_reference(p))
0048 //        Manages p without checking its type
0049 //
0050 //    * get_managed_object(x, boost::python::tag)
0051 //        Convertible to PyObject*
0052 //
0053 // Additional requirements if T can be converted from_python:
0054 //
0055 //    * T(object_manager_traits<T>::adopt(p))
0056 //        steals a reference to p, or throws a TypeError exception if
0057 //        p doesn't have an appropriate type. May assume p is non-null
0058 //
0059 //    * X::check(p)
0060 //        convertible to bool. True iff T(X::construct(p)) will not
0061 //        throw.
0062 
0063 // Forward declarations
0064 //
0065 namespace boost { namespace python
0066 {
0067   namespace api
0068   {
0069     class object; 
0070   }
0071 }}
0072 
0073 namespace boost { namespace python { namespace converter { 
0074 
0075 
0076 // Specializations for handle<T>
0077 template <class T>
0078 struct handle_object_manager_traits
0079     : pyobject_traits<typename T::element_type>
0080 {
0081  private:
0082   typedef pyobject_traits<typename T::element_type> base;
0083   
0084  public:
0085   BOOST_STATIC_CONSTANT(bool, is_specialized = true);
0086 
0087   // Initialize with a null_ok pointer for efficiency, bypassing the
0088   // null check since the source is always non-null.
0089   static null_ok<typename T::element_type>* adopt(PyObject* p)
0090   {
0091       return python::allow_null(base::checked_downcast(p));
0092   }
0093 };
0094 
0095 template <class T>
0096 struct default_object_manager_traits
0097 {
0098     BOOST_STATIC_CONSTANT(
0099         bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
0100         );
0101 };
0102 
0103 template <class T>
0104 struct object_manager_traits
0105     : mpl::if_c<
0106          is_handle<T>::value
0107        , handle_object_manager_traits<T>
0108        , default_object_manager_traits<T>
0109     >::type
0110 {
0111 };
0112 
0113 //
0114 // Traits for detecting whether a type is an object manager or a
0115 // (cv-qualified) reference to an object manager.
0116 // 
0117 
0118 template <class T>
0119 struct is_object_manager
0120     : mpl::bool_<object_manager_traits<T>::is_specialized>
0121 {
0122 };
0123 
0124 template <class T>
0125 struct is_reference_to_object_manager
0126     : mpl::false_
0127 {
0128 };
0129 
0130 template <class T>
0131 struct is_reference_to_object_manager<T&>
0132     : is_object_manager<T>
0133 {
0134 };
0135 
0136 template <class T>
0137 struct is_reference_to_object_manager<T const&>
0138     : is_object_manager<T>
0139 {
0140 };
0141 
0142 template <class T>
0143 struct is_reference_to_object_manager<T volatile&>
0144     : is_object_manager<T>
0145 {
0146 };
0147 
0148 template <class T>
0149 struct is_reference_to_object_manager<T const volatile&>
0150     : is_object_manager<T>
0151 {
0152 };
0153 
0154 }}} // namespace boost::python::converter
0155 
0156 #endif // OBJECT_MANAGER_DWA2002614_HPP