A possible solution for the opIndexXxxAssign morass

Fawzi Mohamed fmohamed at mac.com
Thu Oct 15 14:09:26 PDT 2009


On 2009-10-15 22:55:02 +0200, Fawzi Mohamed <fmohamed at mac.com> said:

> On 2009-10-15 17:51:56 +0200, "Robert Jacques" <sandford at jhu.edu> said:
> 
>> On Thu, 15 Oct 2009 04:48:57 -0400, Fawzi Mohamed <fmohamed at mac.com> wrote:
>> 
>>> [...]
>>> Note that a ref return for opIndex, could work in most situations.
>>> As Bill correctly pointed out sparse matrix offer the most challenging  
>>> example, there one wants to have two different functions: opIndex and  
>>> opIndexLhs, the second being called when the index is on the left hand  
>>> side of an assignment, so that reading a 0 entry in a matrix returns 0, 
>>>  whereas assigning it allocates place for it.
>>> This makes it slightly more complex to control what is being assigned  
>>> (as you need to return a structure overloading opXAssign, but I think 
>>> it  would be ok in most cases.
>>> 
>>> Fawzi
>>> 
>> 
>> Would you like some example code?
> 
> I suppose you would like it ;)
> 
> // example 1
> class Matrix(T){
>   T opIndex(size_t i,size_t j){
>     if (has_(i,j)){
>       return data[index(i,j)];
>     } else {
>       return cast(T)0;
>     }
>   }
>   ref T opIndexLhs(size_t i,size_t j){
>     if (has_(i,j)){
>       return &data[index(i,j)];
>     } else {
>       //alloc new place and set things so that index(i,j) returns it
>       return &data[index(i,j)];
>     }
>   }
> }

mmmh I mixed up a bit the ref returning and pointer returning case...
clearly there should be no &...

> 
> then
> m[3,4]+=4.0;
> would be converted in
> m.opIndexLhs(3,4)+=4.0;
> 
> typically with just one method (opIndexLhs) all += -=,... are covered
> 
> if one needs more control
> 
> class AbsMatrix(T){
>   T opIndex(size_t i,size_t j){
>     if (has_(i,j)){
>       return data[index(i,j)];
>     } else {
>       return cast(T)0;
>     }
>   }
>   struct Setter{
>     T* pos;
>      void opAddAssign(T val){
>        *pos+=abs(val);
>      }
>   }
>   Setter opIndexLhs(size_t i,size_t j){
>     Setter pos;
>     if (has_(i,j)){
>        res.pos=&data[index(i,j)];
>     } else {
>       //alloc new place and set things so that index(i,j) returns it
>       res.pos=&data[index(i,j)];
>     }
>     return res;
>   }
> }
> 
> if one does not allow ref T as return type then one can return a pointer and do
> static if(is(typeof(*m.opIndexLhs(3,4))))
> 	*m.opIndexLhs(3,4)+=4.0;
> else
> 	m.opIndexLhs(3,4)+=4.0;
> 
> so that the trick with the struct is still possible.





More information about the Digitalmars-d mailing list