[C++-sig] contained structure access
David Abrahams
dave at boost-consulting.com
Thu Nov 7 21:45:27 CET 2002
Graeme Lufkin <gwl at u.washington.edu> writes:
>>> I tried
>>> .def("__getitem__", &MyClass::operator[])
>>> but it complained about sizeof() being applied to an unspecified
>>> type.
>>
>>Can you show the complete error message?
> Aha, I wasn't being precise enough. My operator[] returns a reference,
> so that I can do things like
> m = MyClass()
> m[0] = 3.14
> m[2] = 2.71828
> If I change my operator[] to return a value, the .def() works, and I can
> access the values. If I leave it as returning a reference, and use
> return_internal_reference<>, it doesn't compile. Here's the code:
>
> struct Atom {
> double x, y, z;
> double& operator[](const int i) {
> switch(i) {
> case 0: return x;
> case 1: return y;
> case 2: return z;
> }
> return x;
> }
> };
> class_<Atom>("Atom")
> .def_readwrite("x", &Atom::x)
> .def_readwrite("y", &Atom::y)
> .def_readwrite("z", &Atom::z)
> .def("__getitem__", &Atom::operator[], return_internal_reference<>());
>
> Given this, I get a long error chain with tons of templated goodness,
> the last few 'instantied from's of which follow:
So, did you look at this line?
> /net/mondo-1/nbody/gwl/projects/boost_1_29_0/boost/python/object/make_instance.hpp:22:
> `sizeof' applied to incomplete type
> `boost::STATIC_ASSERTION_FAILURE<false>'
The source line is:
BOOST_STATIC_ASSERT(is_class<T>::value);
Which means you can only return a reference to an object of class
type. Since double is not of class type, it complains.
Why don't you use return_value_policy<copy_non_const_reference>
instead?
http://www.boost.org/libs/python/doc/v2/copy_non_const_reference.html
> Hey, you asked for it! Seriously, if you want the whole thing, I'll
> email it to you directly.
>
> The other question: I'm still not sure I understand the business with
> properties and return_internal_reference<>. I don't get why the extra
> level of member-ness (i.e. x.y.z) reveals the copy business, which
> doesn't appear one level lower (i.e. x.y). But I can make it work, so
> maybe I'll just forget it.
Just remember that when reading a property, the result is returned by
value unless you specify otherwise. So x.y.z = 1 becomes
setattr(getattr(x, "y"), "z", 1)
If you don't do something explicit to prevent it, getattr(x, "y")
returns a copy of x's y member, so assigning to its z element changes
the wrong object.
> Regarding the *= float(), I'm using python 2.2, and will live with
> doing 'v = v * 2' until I can upgrade.
> Also, I commend you (Dave) on your ridiculously fast response time.
> You're making my life easier.
That's the aim. I just wish I had a little more time to spend on the
Boost.Python code.
--
David Abrahams
dave at boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution
More information about the Cplusplus-sig
mailing list