📄 object_manager.hpp
字号:
// 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_SPECIALIZATIONtemplate <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>{};# elsenamespace 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -