[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