Thread: [pygccxml-development] __getitem__ / __setitem__
Brought to you by:
mbaas,
roman_yakovenko
From: Matthias B. <ba...@ir...> - 2006-09-28 08:42:59
|
Hi, Py++ turns index operators into a __getitem__() method. Now I was just wondering if it should also create a __setitem__() method when there's an operator that returns a reference? I have some cases where this would be desirable (but I don't know if it's desirable in every case). For example, the Maya vector classes define operators like these: double& operator[] ( unsigned i ); double operator[] ( unsigned i ) const; So far, I was ignoring the first one and only wrapped the second one which was correctly turned into a __getitem__() method (but of course, this meant I couldn't assign values via the index operator). In this case, the first operator could actually spawn a __setitem__() method as well. I have no problems with doing that manually, but I was just wondering if this could/should be made an (optional?) builtin functionality of Py++ and so I'm just throwing in the idea... - Matthias - |
From: Matthias B. <ba...@ir...> - 2006-09-28 13:11:57
|
Roman Yakovenko wrote: >> Py++ turns index operators into a __getitem__() method. Now I was just >> wondering if it should also create a __setitem__() method when there's >> an operator that returns a reference? >> [...] > > double& operator[]( unsinged i ) > > ==> > > void __setitem__( unsigned i, double value ){ > this->operator[]( i ) = value; > } > > This is what you mean, right? Yes. > It could be done, it should not be a problem. > If you write test code I can spend few hours on adding this functionality. > Test cases ( instead of double ): > 1. fundamental type ( double is good ) > 2. pointer to some struct > 3. reference to some struct > 4. reference to noncopyable object ( in this case __setitem__ > should not be generated ) > 5. other use cases I missed :-) Well, my own use-cases are of the first type, so they are among the easier ones. I'm not so sure about the other cases when the values are actual objects. Has anybody else here had to wrap index operators? Did you do it manually and have there been any special situations? What are your thoughts about such a feature? - Matthias - |
From: Matthias B. <ba...@ir...> - 2006-09-29 19:08:48
|
Roman Yakovenko wrote: > If you write test code I can spend few hours on adding this functionality. > Test cases ( instead of double ): > 1. fundamental type ( double is good ) > 2. pointer to some struct > 3. reference to some struct > 4. reference to noncopyable object ( in this case __setitem__ > should not be generated ) > 5. other use cases I missed :-) I have written some sample code that contains a few test scenarios (see below). I could imagine that something like the below double_array_2 class could be problematic because it has a single operator that should generate two separate Python methods. (Each of the below cases could also be extended by adding a function transformer that checks the range of the index, for example) - Matthias - /* This class only provides an index operator that does not return a reference. The wrapper class should only contain a __getitem__() method and no __setitem__() method. */ struct double_array_1 { double dummy_array[2]; double_array_1() { dummy_array[0] = 0; dummy_array[1] = 0; } double operator[](unsigned int i) const { return dummy_array[i]; } }; /* This class only provides a single index operator that returns a reference. The index operator can be used for both, reading and writing values, so the wrapper class should contain __getitem__ and __setitem__. */ struct double_array_2 { double dummy_array[2]; double_array_2() { dummy_array[0] = 0; dummy_array[1] = 0; } double& operator[](unsigned int i) { return dummy_array[i]; } }; /* This class provides two index operators. The wrapper class should be the same as in double_array_2, the additional operator doesn't have a visible effect to the Python bindings (in particular, there should not be two __getitem__ methods). */ struct double_array_3 { double dummy_array[2]; double_array_3() { dummy_array[0] = 0; dummy_array[1] = 0; } double& operator[](unsigned int i) { return dummy_array[i]; } double operator[](unsigned int i) const { return dummy_array[i]; } }; ////////////////////////////////////////////////////////////////////// /* The following two array classes use a custom defined item class (instead of a fundamental type). */ struct item { double value; item(double val=0) : value(val) {} }; struct item_array_1 { item dummy_array[2]; item& operator[](unsigned int i) { return dummy_array[i]; } }; struct item_array_2 { item dummy_array[2]; // Return a const item. This can not (!) be used for __setitem__ const item& operator[](unsigned int i) { return dummy_array[i]; } }; ////////////////////////////////////////////////////////////////////// /* The following item defines a private assignment operator, so __setitem__ is not possible. */ struct item2 { double value; item2(double val=0) : value(val) {} private: item2& operator=(const item2& other) { std::cout<<"FOO"<<std::endl; return *this; } }; struct item2_array_1 { item2 dummy_array[2]; item2& operator[](unsigned int i) { return dummy_array[i]; } }; |