diff --git a/include/boost/python/detail/copy_ctor_mutates_rhs.hpp b/include/boost/python/detail/copy_ctor_mutates_rhs.hpp new file mode 100755 index 00000000..57c3d403 --- /dev/null +++ b/include/boost/python/detail/copy_ctor_mutates_rhs.hpp @@ -0,0 +1,64 @@ +// Copyright David Abrahams 2003. 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. +#include +#ifndef BOOST_NO_AUTO_PTR +# include +#endif + +#ifndef COPY_CTOR_MUTATES_RHS_DWA2003219_HPP +# define COPY_CTOR_MUTATES_RHS_DWA2003219_HPP + +namespace boost { namespace python { namespace detail { + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_AUTO_PTR) + +template +struct is_auto_ptr +{ + typedef char yes; + typedef char (&no)[2]; + + static + T& f(); + + template + static yes test(std::auto_ptr&, int); + + template + static no test(U&, ...); + + BOOST_STATIC_CONSTANT( + bool, value = sizeof(test(f(), 0)) == sizeof(yes)); + + typedef mpl::bool_c type; + +}; + +# else + +template +struct is_auto_ptr : mpl::false_c +{ +}; + +# if !defined(BOOST_NO_AUTO_PTR) +template +struct is_auto_ptr > : mpl::true_c +{ +}; + +# endif +# endif + +template +struct copy_ctor_mutates_rhs + : is_auto_ptr +{ +}; + +}}} // namespace boost::python::detail + +#endif // COPY_CTOR_MUTATES_RHS_DWA2003219_HPP diff --git a/include/boost/python/extract.hpp b/include/boost/python/extract.hpp index 598fe249..27a0b60d 100644 --- a/include/boost/python/extract.hpp +++ b/include/boost/python/extract.hpp @@ -11,12 +11,13 @@ # include # include # include -# include # include -# include # include # include # include +# include +# include +# include namespace boost { namespace python { @@ -53,7 +54,12 @@ namespace converter template struct extract_rvalue : private noncopyable { - typedef typename call_traits::param_type result_type; + typedef typename mpl::if_< + python::detail::copy_ctor_mutates_rhs + , T& + , typename call_traits::param_type + >::type result_type; + extract_rvalue(PyObject*); bool check() const; diff --git a/test/auto_ptr.cpp b/test/auto_ptr.cpp index ad682304..1de51f23 100644 --- a/test/auto_ptr.cpp +++ b/test/auto_ptr.cpp @@ -66,10 +66,17 @@ BOOST_PYTHON_MODULE(auto_ptr_ext) .def("value", &X::value) ; - class_, bases, boost::noncopyable>("X", init()) + class_, bases, boost::noncopyable>("Y", init()) ; + // VC6 auto_ptrs do not have converting constructors +#if defined(BOOST_MSVC_STD_ITERATOR) + scope().attr("broken_auto_ptr") = 1; +#else + scope().attr("broken_auto_ptr") = 0; implicitly_convertible, std::auto_ptr >(); +#endif + def("look", look); def("steal", steal); def("maybe_steal", maybe_steal); diff --git a/test/auto_ptr.py b/test/auto_ptr.py index e31feb25..426a5d84 100644 --- a/test/auto_ptr.py +++ b/test/auto_ptr.py @@ -13,13 +13,13 @@ >>> maybe_steal(x, 1) 42 ->>> (not '--broken-auto-ptr' in sys.argv) and look(x) or -1 +>>> broken_auto_ptr and -1 or look(x) -1 >>> x = X(69) >>> steal(x) 69 ->>> (not '--broken-auto-ptr' in sys.argv) and look(x) or -1 +>>> broken_auto_ptr and -1 or look(x) -1 >>> if not '--broken-auto-ptr' in sys.argv: @@ -46,9 +46,6 @@ >>> y.value() 42 ->>> maybe_steal(y, 0) -42 - >>> try: maybe_steal(y, 0) ... except TypeError: pass ... else: print 'expected a TypeError exception' @@ -56,10 +53,10 @@ >>> y.value() 42 ->>> steal(y) +>>> broken_auto_ptr and 42 or steal(y) 42 ->>> if not '--broken-auto-ptr' in sys.argv: +>>> if not broken_auto_ptr: ... try: y.value() ... except TypeError: pass ... else: print 'expected a TypeError exception' diff --git a/test/copy_ctor_mutates_rhs.cpp b/test/copy_ctor_mutates_rhs.cpp new file mode 100755 index 00000000..473b7a66 --- /dev/null +++ b/test/copy_ctor_mutates_rhs.cpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2003. 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. +#include +#include +#include +#include + +struct foo +{ + operator std::auto_ptr&() const; +}; + +int main() +{ + using namespace boost::python::detail; + BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); + BOOST_STATIC_ASSERT(copy_ctor_mutates_rhs >::value); + BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); + BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); +}