mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 06:02:14 +00:00
implemented back_reference<>
[SVN r13811]
This commit is contained in:
97
include/boost/python/back_reference.hpp
Normal file
97
include/boost/python/back_reference.hpp
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BACK_REFERENCE_DWA2002510_HPP
|
||||
# define BACK_REFERENCE_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/reference.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
struct back_reference
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
back_reference(PyObject*, T);
|
||||
ref reference() const;
|
||||
T get() const;
|
||||
private:
|
||||
ref m_reference;
|
||||
T m_value;
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
class is_back_reference
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_back_reference<back_reference<T> >
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
# else // no partial specialization
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_back_reference_t)[1];
|
||||
typedef char (&no_back_reference_t)[2];
|
||||
|
||||
no_back_reference_t is_back_reference_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_back_reference_t is_back_reference_test(type< back_reference<T> >);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class is_back_reference
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_back_reference_test(type<T>()))
|
||||
== sizeof(detail::yes_back_reference_t)));
|
||||
};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T>
|
||||
back_reference<T>::back_reference(PyObject* p, T x)
|
||||
: m_reference(p, ref::increment_count)
|
||||
, m_value(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
ref back_reference<T>::reference() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T back_reference<T>::get() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BACK_REFERENCE_DWA2002510_HPP
|
||||
@@ -16,6 +16,12 @@
|
||||
# include <boost/python/converter/lvalue_from_python_chain.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_chain.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T> struct from_python;
|
||||
}}
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -82,6 +88,21 @@ class rvalue_from_python
|
||||
rvalue_data<result_type> m_data;
|
||||
};
|
||||
|
||||
// ------- back-reference converters --------
|
||||
|
||||
// Converts to a (PyObject*,T) bundle, for when you need a reference
|
||||
// back to the Python object
|
||||
|
||||
template <class T>
|
||||
struct back_reference_from_python
|
||||
: boost::python::from_python<typename T::type>
|
||||
{
|
||||
back_reference_from_python(PyObject*);
|
||||
T operator()(PyObject*);
|
||||
private:
|
||||
typedef boost::python::from_python<typename T::type> base;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_from_python
|
||||
{
|
||||
@@ -100,6 +121,10 @@ struct select_from_python
|
||||
boost::python::detail::is_reference_to_non_const<T>::value
|
||||
|| boost::python::detail::is_reference_to_volatile<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, back_ref =
|
||||
boost::python::is_back_reference<T>::value);
|
||||
|
||||
typedef typename mpl::select_type<
|
||||
ptr
|
||||
, pointer_from_python<T>
|
||||
@@ -109,7 +134,11 @@ struct select_from_python
|
||||
, typename mpl::select_type<
|
||||
ref
|
||||
, reference_from_python<T>
|
||||
, rvalue_from_python<T>
|
||||
, typename mpl::select_type<
|
||||
back_ref
|
||||
, back_reference_from_python<T>
|
||||
, rvalue_from_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
@@ -232,6 +261,19 @@ rvalue_from_python<T>::operator()(PyObject* p)
|
||||
return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
back_reference_from_python<T>::back_reference_from_python(PyObject* x)
|
||||
: base(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
back_reference_from_python<T>::operator()(PyObject* x)
|
||||
{
|
||||
return T(x, base::operator()(x));
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_DWA2002127_HPP
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/has_back_reference.hpp>
|
||||
#include <boost/python/back_reference.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <memory>
|
||||
@@ -73,6 +74,17 @@ namespace boost { namespace python
|
||||
};
|
||||
}}
|
||||
|
||||
// prove that back_references get initialized with the right PyObject*
|
||||
PyObject* y_identity(back_reference<Y const&> y)
|
||||
{
|
||||
return y.reference().release();
|
||||
}
|
||||
|
||||
// prove that back_references contain the right value
|
||||
bool y_equality(back_reference<Y const&> y1, Y const& y2)
|
||||
{
|
||||
return &y1.get() == &y2;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(back_reference_ext)
|
||||
{
|
||||
@@ -93,6 +105,8 @@ BOOST_PYTHON_MODULE_INIT(back_reference_ext)
|
||||
.def("value", &Z::value)
|
||||
.def("set", &Z::set)
|
||||
)
|
||||
.def("y_identity", y_identity)
|
||||
.def("y_equality", y_equality)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
>>> z2 = copy_Z(z)
|
||||
>>> x_instances()
|
||||
4
|
||||
>>> y_identity(y) is y
|
||||
1
|
||||
>>> y_equality(y, y)
|
||||
1
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
Reference in New Issue
Block a user