2
0
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:
Dave Abrahams
2002-05-10 15:48:27 +00:00
parent 63deae3ab2
commit 390bb1988d
4 changed files with 158 additions and 1 deletions

View 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

View File

@@ -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

View File

@@ -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)
;
}

View File

@@ -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):