diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 8dede0e3..7f31df88 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -9,6 +9,7 @@ # include # include # include +# include # include # include # include @@ -32,12 +33,6 @@ namespace // put some convenience classes into the unnamed namespace for the use namespace boost { namespace python { -// Forward declarations -namespace objects -{ - struct value_holder_generator; -} - namespace detail { // This is an mpl BinaryMetaFunction object with a runtime behavior, diff --git a/include/boost/python/class_fwd.hpp b/include/boost/python/class_fwd.hpp index 6faf7aae..bef2e250 100644 --- a/include/boost/python/class_fwd.hpp +++ b/include/boost/python/class_fwd.hpp @@ -5,6 +5,7 @@ // to its suitability for any purpose. #ifndef CLASS_FWD_DWA200222_HPP # define CLASS_FWD_DWA200222_HPP +# include namespace boost { namespace python { @@ -13,15 +14,10 @@ namespace detail struct empty_list; } -namespace objects -{ - struct value_holder_generator; -} - template < class T // class being wrapped , class Bases = detail::empty_list - , class HolderGenerator = objects::value_holder_generator + , class HolderGenerator = objects::value_holder_generator<> > class class_; diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 0d5210c7..d453967c 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -11,7 +11,6 @@ # include # include # include -# include # include namespace boost { namespace python { @@ -55,24 +54,6 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable virtual void* holds(converter::undecorated_type_id_t) = 0; void install(PyObject* inst) throw(); - - struct iterator_policies : default_iterator_policies - { - template - void increment(Iterator& p) - { - p.base() = p.base()->next(); - } - }; - - typedef iterator_adaptor< - instance_holder* - , iterator_policies - , value_type_is - , reference_is - , pointer_is - , iterator_category_is > iterator; - private: instance_holder* m_next; }; diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 825e02b0..1ba6f932 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -22,7 +22,7 @@ struct make_holder<0> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; static void execute( PyObject* p) { @@ -38,7 +38,7 @@ struct make_holder<1> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; @@ -57,7 +57,7 @@ struct make_holder<2> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -77,7 +77,7 @@ struct make_holder<3> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -99,7 +99,7 @@ struct make_holder<4> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -123,7 +123,7 @@ struct make_holder<5> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -149,7 +149,7 @@ struct make_holder<6> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index c307f019..2722ae85 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -12,6 +12,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -145,7 +146,137 @@ struct pointer_holder : instance_holder Pointer m_p; }; -}}} +template +struct pointer_holder_back_reference : instance_holder +{ + pointer_holder_back_reference(Pointer); + + // Forward construction to the held object + pointer_holder_back_reference(PyObject* p) + : m_p(new Value(p)) {} + + + template + pointer_holder_back_reference(PyObject* p, A1 a1) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + )) {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + )) {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + , (typename unwrap_reference::type&)(a10) + )) + {} + + private: // required holder implementation + void* holds(converter::undecorated_type_id_t); + + private: // data members + Pointer m_p; +}; + +}}} // namespace boost::python::objects // back to namespace boost for this forward declaration namespace boost @@ -164,19 +295,54 @@ struct shared_ptr_generator }; }; +struct no_back_reference; + +// Workaround lack of partial specialization +namespace detail +{ + template + struct pointer_holder_back_reference_generator + { + template + struct apply + { + typedef typename boost::python::detail::eval< + PointerGenerator,BackReferenceType + >::type pointer; + + typedef pointer_holder_back_reference type; + }; + }; + + template + struct plain_pointer_holder_generator + { + template + struct apply + { + typedef typename boost::python::detail::eval< + PointerGenerator,Held + >::type pointer; + + typedef pointer_holder type; + }; + }; +} + // A generator metafunction which can be passed to make_holder // PointerGenerator should be another generator metafunction which // makes the appropriate (smart) pointer type to hold the argument to // pointer_holder_generator. -template +template struct pointer_holder_generator + : mpl::select_type< + is_same::value + , detail::plain_pointer_holder_generator< + PointerGenerator> + , detail::pointer_holder_back_reference_generator< + BackReferenceType,PointerGenerator> + >::type { - template - struct apply - { - typedef typename detail::eval::type pointer; - typedef pointer_holder type; - }; }; template diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 6533bc39..62222a23 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -6,6 +6,7 @@ #ifndef VALUE_HOLDER_DWA20011215_HPP # define VALUE_HOLDER_DWA20011215_HPP +# include # include # include # include @@ -140,8 +141,136 @@ struct value_holder : instance_holder Held m_held; }; +template +struct value_holder_back_reference : instance_holder +{ + // Forward construction to the held object + value_holder_back_reference(PyObject* p) + : m_held() {} + + template + value_holder_back_reference(PyObject* p, A1 a1) + : m_held(p + , (typename unwrap_reference::type&)(a1) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + ) {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + ) {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + , (typename unwrap_reference::type&)(a10) + ) + {} + + private: // required holder implementation + void* holds(converter::undecorated_type_id_t); + + private: // data members + BackReferenceType m_held; +}; + // A generator metafunction which can be passed to make_holder -struct value_holder_generator +template <> +struct value_holder_generator { template struct apply @@ -150,6 +279,16 @@ struct value_holder_generator }; }; +template +struct value_holder_generator +{ + template + struct apply + { + typedef value_holder_back_reference type; + }; +}; + template void* value_holder::holds(converter::undecorated_type_id_t dst_t) { @@ -158,6 +297,23 @@ void* value_holder::holds(converter::undecorated_type_id_t dst_t) : find_static_type(&m_held, src_t, dst_t); } +template +void* value_holder_back_reference::holds( + converter::undecorated_type_id_t dst_t) +{ + converter::undecorated_type_id_t src_t = converter::undecorated_type_id(); + if (src_t == dst_t) + { + Held* x = &m_held; + return x; + } + + src_t = converter::undecorated_type_id(); + return src_t == dst_t + ? &m_held + : find_static_type(&m_held, src_t, dst_t); +} + }}} // namespace boost::python::objects #endif // VALUE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/object/value_holder_fwd.hpp b/include/boost/python/object/value_holder_fwd.hpp new file mode 100644 index 00000000..6cb2a0f5 --- /dev/null +++ b/include/boost/python/object/value_holder_fwd.hpp @@ -0,0 +1,17 @@ +// 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 VALUE_HOLDER_FWD_DWA2002311_HPP +# define VALUE_HOLDER_FWD_DWA2002311_HPP + +namespace boost { namespace python { namespace objects { + +struct no_back_reference; + +template struct value_holder_generator; + +}}} // namespace boost::python::object + +#endif // VALUE_HOLDER_FWD_DWA2002311_HPP diff --git a/src/object/class.cpp b/src/object/class.cpp index b9deb98f..dc3a42af 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -169,9 +169,9 @@ find_instance_impl(PyObject* inst, converter::undecorated_type_id_t type) instance* self = reinterpret_cast(inst); - for (instance_holder::iterator match(self->objects), end(0); match != end; ++match) + for (instance_holder* match = self->objects; match != 0; match = match->next()) { - void* const found = (*match).holds(type); + void* const found = match->holds(type); if (found) return found; }