[C++-sig] V2: corner case bug?
David Abrahams
david.abrahams at rcn.com
Thu Apr 4 02:16:59 CEST 2002
Hi Peter,
Thanks for uncovering this!
Here's what's going on:
* In C++, a const& argument can bind to a temporary rvalue.
* Various from_python converters create the equivalent of temporaries.
For example, a converter which produces a std::vector from a Python
tuple must create a value which won't persist past the call being
executed.
* When the library detects that it can bind a temporary of type T to a
given argument, it must produce storage into which that temporary can be
constructed.
* To do so, it asks what boost::aligmnent_of<T>::value is.
Unfortunately, detecting the alignment of T can only compile when T
doesn't have unimplemented pure virtual functions.
I spent all day thinking that we'd need one or both of the following:
1. A way to tell the library not to do that for T. I think this
amounts to a user-specializable is_abstract<T> traits class.
Upside:
Users could stop specifying noncopyable as an optional
class_<> parameter if they specialized is_abstract<T>.
Downside:
This is a cumbersome interface technique for users, requiring
closing
their namespace and opening namespace boost::python. It's prone to
errors: users may not expose the traits specialization to all
modules converting T parameters, especially in designs where
wrapping is an independent, non-intrusive layer from the code being
wrapped. We could mitigate some of the encumberance by asking a user
to declare a function like:
bool operator==(T const&, boost::python::abstract);
in her own namespace to indicate abstract-ness. However, that idiom
is not exactly transparent, and doesn't fix the error-prone-ness.
2. A way to tell the library not to do that for a particular
argument. In other words, "do NOT bind this argument to an rvalue".
One way for the user to approximate this is to wrap a forwarding
function taking a T& argument. Having this capability in the library
would undoubtedly be useful, but it would be non-trivial to
implement
and I'm not sure the added complexity is a good idea, either for
the implementation or for the interface.
Fortunately, there is an alternative which I just thought of:
3. instead of asking for the alignment of T, I can simply produce
my best guess at maximally-aligned storage. Downsides: more stack
memory used per wrapped C++ function (trivial). Can never check that
the storage is in fact appropriately aligned, whether or not T is
abstract (because I'll get errors if T /is/ abstract). Upsides:
simplicity for users. Easy to implement. I can check my alignment
asumptions when T is exposed as a class, as long as noncopyable
isn't specified.
I'm planning to implement 3 unless I hear otherwise from people.
-Dave
----- Original Message -----
From: "Peter Bienstman" <pbienst at MIT.EDU>
To: <c++-sig at python.org>
Sent: Tuesday, April 02, 2002 6:02 PM
Subject: [C++-sig] V2: corner case bug?
> OK, this odd combination of abstract base classes, referencing
existing
> objects and adding new functions to a class does not compile.
>
> Wrapping the 'inside' functions goes fine, wrapping the similar
> 'outside' functions doesn't compile because the compiler wants to
> instantiate the abstract class, although it's marked noncopyable.
>
> #define BOOST_PYTHON_DYNAMIC_LIB
> #define BOOST_PYTHON_V2
>
> #include <boost/python/module.hpp>
> #include <boost/python/class.hpp>
> #include <boost/python/reference_existing_object.hpp>
> #include <boost/python/return_value_policy.hpp>
>
> struct A {};
>
> struct V
> {
>
> virtual void f() = 0;
>
> const A* inside() {return &a;}
>
> A a;
> };
>
> const A* outside(const V& v) {return &v.a;}
>
> BOOST_PYTHON_MODULE_INIT(m)
> {
> using namespace boost::python;
> using boost::shared_ptr;
> using boost::python::return_value_policy;
> using boost::python::reference_existing_object;
>
> module m("m");
>
> m
> .add(class_<A, shared_ptr<A> >("A"))
>
> .add(
> class_<V, boost::noncopyable>("V")
> .def("inside", &V::inside,
> return_value_policy<reference_existing_object>())
> .def("outside", outside,
> return_value_policy<reference_existing_object>())
> )
> ;
> }
>
>
>
>
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig
>
More information about the Cplusplus-sig
mailing list