diff DEPENDENCIES/generic/include/boost/python/converter/object_manager.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/generic/include/boost/python/converter/object_manager.hpp	Tue Aug 05 11:11:38 2014 +0100
@@ -0,0 +1,230 @@
+// Copyright David Abrahams 2002.
+// 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 OBJECT_MANAGER_DWA2002614_HPP
+# define OBJECT_MANAGER_DWA2002614_HPP
+
+# include <boost/python/handle.hpp>
+# include <boost/python/cast.hpp>
+# include <boost/python/converter/pyobject_traits.hpp>
+# include <boost/type_traits/object_traits.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/python/detail/indirect_traits.hpp>
+# include <boost/mpl/bool.hpp>
+
+// Facilities for dealing with types which always manage Python
+// objects. Some examples are object, list, str, et. al. Different
+// to_python/from_python conversion rules apply here because in
+// contrast to other types which are typically embedded inside a
+// Python object, these are wrapped around a Python object. For most
+// object managers T, a C++ non-const T reference argument does not
+// imply the existence of a T lvalue embedded in the corresponding
+// Python argument, since mutating member functions on T actually only
+// modify the held Python object.
+//
+// handle<T> is an object manager, though strictly speaking it should
+// not be. In other words, even though mutating member functions of
+// hanlde<T> actually modify the handle<T> and not the T object,
+// handle<T>& arguments of wrapped functions will bind to "rvalues"
+// wrapping the actual Python argument, just as with other object
+// manager classes. Making an exception for handle<T> is simply not
+// worth the trouble.
+//
+// borrowed<T> cv* is an object manager so that we can use the general
+// to_python mechanisms to convert raw Python object pointers to
+// python, without the usual semantic problems of using raw pointers.
+
+
+// Object Manager Concept requirements:
+//
+//    T is an Object Manager
+//    p is a PyObject*
+//    x is a T
+//
+//    * object_manager_traits<T>::is_specialized == true
+//
+//    * T(detail::borrowed_reference(p))
+//        Manages p without checking its type
+//
+//    * get_managed_object(x, boost::python::tag)
+//        Convertible to PyObject*
+//
+// Additional requirements if T can be converted from_python:
+//
+//    * T(object_manager_traits<T>::adopt(p))
+//        steals a reference to p, or throws a TypeError exception if
+//        p doesn't have an appropriate type. May assume p is non-null
+//
+//    * X::check(p)
+//        convertible to bool. True iff T(X::construct(p)) will not
+//        throw.
+
+// Forward declarations
+//
+namespace boost { namespace python
+{
+  namespace api
+  {
+    class object; 
+  }
+}}
+
+namespace boost { namespace python { namespace converter { 
+
+
+// Specializations for handle<T>
+template <class T>
+struct handle_object_manager_traits
+    : pyobject_traits<typename T::element_type>
+{
+ private:
+  typedef pyobject_traits<typename T::element_type> base;
+  
+ public:
+  BOOST_STATIC_CONSTANT(bool, is_specialized = true);
+
+  // Initialize with a null_ok pointer for efficiency, bypassing the
+  // null check since the source is always non-null.
+  static null_ok<typename T::element_type>* adopt(PyObject* p)
+  {
+      return python::allow_null(base::checked_downcast(p));
+  }
+};
+
+template <class T>
+struct default_object_manager_traits
+{
+    BOOST_STATIC_CONSTANT(
+        bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
+        );
+};
+
+template <class T>
+struct object_manager_traits
+    : mpl::if_c<
+         is_handle<T>::value
+       , handle_object_manager_traits<T>
+       , default_object_manager_traits<T>
+    >::type
+{
+};
+
+//
+// Traits for detecting whether a type is an object manager or a
+// (cv-qualified) reference to an object manager.
+// 
+
+template <class T>
+struct is_object_manager
+    : mpl::bool_<object_manager_traits<T>::is_specialized>
+{
+};
+
+# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+template <class T>
+struct is_reference_to_object_manager
+    : mpl::false_
+{
+};
+
+template <class T>
+struct is_reference_to_object_manager<T&>
+    : is_object_manager<T>
+{
+};
+
+template <class T>
+struct is_reference_to_object_manager<T const&>
+    : is_object_manager<T>
+{
+};
+
+template <class T>
+struct is_reference_to_object_manager<T volatile&>
+    : is_object_manager<T>
+{
+};
+
+template <class T>
+struct is_reference_to_object_manager<T const volatile&>
+    : is_object_manager<T>
+{
+};
+# else
+
+namespace detail
+{
+  typedef char (&yes_reference_to_object_manager)[1];
+  typedef char (&no_reference_to_object_manager)[2];
+
+  // A number of nastinesses go on here in order to work around MSVC6
+  // bugs.
+  template <class T>
+  struct is_object_manager_help
+  {
+      typedef typename mpl::if_<
+          is_object_manager<T>
+          , yes_reference_to_object_manager
+          , no_reference_to_object_manager
+          >::type type;
+
+      // If we just use the type instead of the result of calling this
+      // function, VC6 will ICE.
+      static type call();
+  };
+
+  // A set of overloads for each cv-qualification. The same argument
+  // is passed twice: the first one is used to unwind the cv*, and the
+  // second one is used to avoid relying on partial ordering for
+  // overload resolution.
+  template <class U>
+  typename is_object_manager_help<U>
+  is_object_manager_helper(U*, void*);
+  
+  template <class U>
+  typename is_object_manager_help<U>
+  is_object_manager_helper(U const*, void const*);
+  
+  template <class U>
+  typename is_object_manager_help<U>
+  is_object_manager_helper(U volatile*, void volatile*);
+  
+  template <class U>
+  typename is_object_manager_help<U>
+  is_object_manager_helper(U const volatile*, void const volatile*);
+  
+  template <class T>
+  struct is_reference_to_object_manager_nonref
+      : mpl::false_
+  {
+  };
+
+  template <class T>
+  struct is_reference_to_object_manager_ref
+  {
+      static T sample_object;
+      BOOST_STATIC_CONSTANT(
+        bool, value
+        = (sizeof(is_object_manager_helper(&sample_object, &sample_object).call())
+            == sizeof(detail::yes_reference_to_object_manager)
+          )
+        );
+      typedef mpl::bool_<value> type;
+  };
+}
+
+template <class T>
+struct is_reference_to_object_manager
+    : mpl::if_<
+        is_reference<T>
+        , detail::is_reference_to_object_manager_ref<T>
+        , detail::is_reference_to_object_manager_nonref<T>
+    >::type
+{
+};
+# endif 
+
+}}} // namespace boost::python::converter
+
+#endif // OBJECT_MANAGER_DWA2002614_HPP