Skip to content

Commit acdad5c

Browse files
committed
better auto_ptr support
[SVN r17592]
1 parent b42b243 commit acdad5c

5 files changed

Lines changed: 108 additions & 11 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright David Abrahams 2003. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#include <boost/mpl/bool_c.hpp>
7+
#ifndef BOOST_NO_AUTO_PTR
8+
# include <memory>
9+
#endif
10+
11+
#ifndef COPY_CTOR_MUTATES_RHS_DWA2003219_HPP
12+
# define COPY_CTOR_MUTATES_RHS_DWA2003219_HPP
13+
14+
namespace boost { namespace python { namespace detail {
15+
16+
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_AUTO_PTR)
17+
18+
template <class T>
19+
struct is_auto_ptr
20+
{
21+
typedef char yes;
22+
typedef char (&no)[2];
23+
24+
static
25+
T& f();
26+
27+
template <class U>
28+
static yes test(std::auto_ptr<U>&, int);
29+
30+
template <class U>
31+
static no test(U&, ...);
32+
33+
BOOST_STATIC_CONSTANT(
34+
bool, value = sizeof(test(f(), 0)) == sizeof(yes));
35+
36+
typedef mpl::bool_c<value> type;
37+
38+
};
39+
40+
# else
41+
42+
template <class T>
43+
struct is_auto_ptr : mpl::false_c
44+
{
45+
};
46+
47+
# if !defined(BOOST_NO_AUTO_PTR)
48+
template <class T>
49+
struct is_auto_ptr<std::auto_ptr<T> > : mpl::true_c
50+
{
51+
};
52+
53+
# endif
54+
# endif
55+
56+
template <class T>
57+
struct copy_ctor_mutates_rhs
58+
: is_auto_ptr<T>
59+
{
60+
};
61+
62+
}}} // namespace boost::python::detail
63+
64+
#endif // COPY_CTOR_MUTATES_RHS_DWA2003219_HPP

include/boost/python/extract.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
# include <boost/python/converter/rvalue_from_python_data.hpp>
1212
# include <boost/python/converter/registered.hpp>
1313
# include <boost/python/converter/registered_pointee.hpp>
14-
# include <boost/python/detail/void_ptr.hpp>
1514
# include <boost/call_traits.hpp>
16-
# include <boost/python/detail/void_return.hpp>
1715
# include <boost/python/object_core.hpp>
1816
# include <boost/python/refcount.hpp>
1917
# include <boost/utility.hpp>
18+
# include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
19+
# include <boost/python/detail/void_ptr.hpp>
20+
# include <boost/python/detail/void_return.hpp>
2021

2122
namespace boost { namespace python {
2223

@@ -53,7 +54,12 @@ namespace converter
5354
template <class T>
5455
struct extract_rvalue : private noncopyable
5556
{
56-
typedef typename call_traits<T>::param_type result_type;
57+
typedef typename mpl::if_<
58+
python::detail::copy_ctor_mutates_rhs<T>
59+
, T&
60+
, typename call_traits<T>::param_type
61+
>::type result_type;
62+
5763
extract_rvalue(PyObject*);
5864

5965
bool check() const;

test/auto_ptr.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,17 @@ BOOST_PYTHON_MODULE(auto_ptr_ext)
6666
.def("value", &X::value)
6767
;
6868

69-
class_<Y, std::auto_ptr<Y>, bases<X>, boost::noncopyable>("X", init<int>())
69+
class_<Y, std::auto_ptr<Y>, bases<X>, boost::noncopyable>("Y", init<int>())
7070
;
7171

72+
// VC6 auto_ptrs do not have converting constructors
73+
#if defined(BOOST_MSVC_STD_ITERATOR)
74+
scope().attr("broken_auto_ptr") = 1;
75+
#else
76+
scope().attr("broken_auto_ptr") = 0;
7277
implicitly_convertible<std::auto_ptr<Y>, std::auto_ptr<X> >();
78+
#endif
79+
7380
def("look", look);
7481
def("steal", steal);
7582
def("maybe_steal", maybe_steal);

test/auto_ptr.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
1414
>>> maybe_steal(x, 1)
1515
42
16-
>>> (not '--broken-auto-ptr' in sys.argv) and look(x) or -1
16+
>>> broken_auto_ptr and -1 or look(x)
1717
-1
1818
1919
>>> x = X(69)
2020
>>> steal(x)
2121
69
22-
>>> (not '--broken-auto-ptr' in sys.argv) and look(x) or -1
22+
>>> broken_auto_ptr and -1 or look(x)
2323
-1
2424
2525
>>> if not '--broken-auto-ptr' in sys.argv:
@@ -46,20 +46,17 @@
4646
>>> y.value()
4747
42
4848
49-
>>> maybe_steal(y, 0)
50-
42
51-
5249
>>> try: maybe_steal(y, 0)
5350
... except TypeError: pass
5451
... else: print 'expected a TypeError exception'
5552
5653
>>> y.value()
5754
42
5855
59-
>>> steal(y)
56+
>>> broken_auto_ptr and 42 or steal(y)
6057
42
6158
62-
>>> if not '--broken-auto-ptr' in sys.argv:
59+
>>> if not broken_auto_ptr:
6360
... try: y.value()
6461
... except TypeError: pass
6562
... else: print 'expected a TypeError exception'

test/copy_ctor_mutates_rhs.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright David Abrahams 2003. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
7+
#include <boost/static_assert.hpp>
8+
#include <memory>
9+
#include <string>
10+
11+
struct foo
12+
{
13+
operator std::auto_ptr<int>&() const;
14+
};
15+
16+
int main()
17+
{
18+
using namespace boost::python::detail;
19+
BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<int>::value);
20+
BOOST_STATIC_ASSERT(copy_ctor_mutates_rhs<std::auto_ptr<int> >::value);
21+
BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<std::string>::value);
22+
BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<foo>::value);
23+
}

0 commit comments

Comments
 (0)