A possible solution for the opIndexXxxAssign morass

Fawzi Mohamed fmohamed at mac.com
Thu Oct 15 13:55:02 PDT 2009


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)];
    }
  }
}

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