www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - reference return values

reply Frank Fischer <Frank_member pathlink.com> writes:
Hi,

is there any way in D to return references to values (e.g. member variables of
an object), like this in C++:

class Matrix {
private:
double* data;

public:
..
double& at(int i, int j) { return data[i + j*rows]; }
..
double& operator()(int i, int j) { return at(i,j); }
} 


Thin one can use this class like this as lvalue:

Matrix m(10,10);
m.at(1,1) = 1.0;
/* or with operators: */
m(1,1) = 1.0;

One can see the two problems here: you need reference return values (or some
equivalent syntax sugar) to use functions with more than zero parameters as
lvalues (properties only work without parameters). 
For this special problem it would perhaps be possible to overload the array []
operator, but this can only be done with one single operator (that's the reason
for using the call operator () in C++).

I want to port some of my matrix-classes to D, and therefore something like this
would be nice.
May 08 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Frank Fischer wrote:

Hi,

is there any way in D to return references to values (e.g. member variables of
an object), like this in C++:

class Matrix {
private:
double* data;

public:
..
double& at(int i, int j) { return data[i + j*rows]; }
..
double& operator()(int i, int j) { return at(i,j); }
} 


Thin one can use this class like this as lvalue:

Matrix m(10,10);
m.at(1,1) = 1.0;
/* or with operators: */
m(1,1) = 1.0;

One can see the two problems here: you need reference return values (or some
equivalent syntax sugar) to use functions with more than zero parameters as
lvalues (properties only work without parameters). 
For this special problem it would perhaps be possible to overload the array []
operator, but this can only be done with one single operator (that's the reason
for using the call operator () in C++).

I want to port some of my matrix-classes to D, and therefore something like this
would be nice.

You can use more then one [][] using a proxy object: This is something I posted before. You'll need to work it into your own problem. Most of the overhead would be optimised away. struct Col { private int [][] array; private int i; static Col opCall(int [][]array, int pos) { Col col; col.array = array; col.i = pos; return col; } int opIndex(int j) { return array[i][j]; } int opIndex(int j, int value) { return array[i][j] = value; } void length(int len) { array.length = len; } } class Array { private int [][] array; this(int size, int size2) { array.length = size; foreach ( inout int [] arr; array) arr.length = size2; } Col opIndex(int i) { return Col(array, i); } } int main (char[][] args) { Array a = new Array(10,10); a[1][0] = 5; a[1][1] = 6; printf("a[1][0] = %d\n", a[1][0]); printf("a[1][1] = %d\n", a[1][1]); return 0; } -- -Anderson: http://badmama.com.au/~anderson/
May 08 2004
parent reply Frank Fischer <Frank_member pathlink.com> writes:
In article <c7is2l$1arh$1 digitaldaemon.com>, J Anderson says...
You can use more then one [][] using a proxy object:  This is something 
I posted before.  You'll need to work it into your own problem.

Most of the overhead would be optimised away.

Well, but that's not more than a workaround. The problem now is what to do, if i need both, a two-parameter operator (for matrix-like access) _and_ a one-parameter operator (for vector-like access) in one class? I cannot use the []-operator for both. And _most_ of the overhead is not _all_, and that's sth I don't like, because speed is an important factor in my case. Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
May 08 2004
next sibling parent hellcatv hotmail.com writes:
can you overload opCall for this (if it's a struct at least)


In article <c7jaoc$21nt$1 digitaldaemon.com>, Frank Fischer says...
In article <c7is2l$1arh$1 digitaldaemon.com>, J Anderson says...
You can use more then one [][] using a proxy object:  This is something 
I posted before.  You'll need to work it into your own problem.

Most of the overhead would be optimised away.

Well, but that's not more than a workaround. The problem now is what to do, if i need both, a two-parameter operator (for matrix-like access) _and_ a one-parameter operator (for vector-like access) in one class? I cannot use the []-operator for both. And _most_ of the overhead is not _all_, and that's sth I don't like, because speed is an important factor in my case. Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)

May 08 2004
prev sibling next sibling parent Mike Wynn <one_mad_alien hotmail.com> writes:
On Sat, 8 May 2004 19:00:28 +0000 (UTC), Frank Fischer
<Frank_member pathlink.com> wrote:

In article <c7is2l$1arh$1 digitaldaemon.com>, J Anderson says...
You can use more then one [][] using a proxy object:  This is something 
I posted before.  You'll need to work it into your own problem.

Most of the overhead would be optimised away.

Well, but that's not more than a workaround. The problem now is what to do, if i need both, a two-parameter operator (for matrix-like access) _and_ a one-parameter operator (for vector-like access) in one class? I cannot use the []-operator for both. And _most_ of the overhead is not _all_, and that's sth I don't like, because speed is an important factor in my case. Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)

opCall return an int * so b[y][x] = v => *b(x, y) = v; so v = b[y][x] = => v = *b(x, y); ---------------------- import std.c.stdio; class B { int[] data; int lw; this( int xw, int yw ) { lw = xw; data=new int[xw*yw]; } int[] opCall( int y ) { return this[y]; } int * opCall( int x, int y ) { return &data[(y*lw)+x]; } int[] opIndex( int y ) { return data[(y*lw)..((y*lw)+lw)]; } void dump() { printf( "data [" ); foreach( int v; data ) { printf( "%d, ", v ); } printf( "]\n" ); } } int main( char[][] argv ) { B b = new B( 2, 2 ); int[] ar = b[0]; printf("ar.length:%d\n", ar.length); ar[0] = 1; ar[1] = 2; *(b(1,1)) =3; *(b(0,1)) =-4; b.dump(); return 1; } ------------------------ I though about having opCall return a struct that overloaded opCatAssign as there is no overloaded opAssign (that I've found) thus struct Element { int * ptr; Element opCatAssign( int i ) { *ptr = i; return *this; } int value() { return *ptr; } } class B { ... as about except .... Element opCall( int x, int y ) { Element rv; rv.ptr = &data[(y*lw)+x]; return rv; } } int main( char[][] argv ) { B b = new B( 2, 2 ); int[] ar = b[0]; printf("ar.length:%d\n", ar.length); ar[0] = 1; ar[1] = 2; b(1,1) ~= 3; b(0,1) ~= -4; b.dump(); return 1; } more overhead for little improvement, still think D needs true rectangular arrays in the form [n,m] etc. like c#. Mike.
May 08 2004
prev sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Frank Fischer wrote:

In article <c7is2l$1arh$1 digitaldaemon.com>, J Anderson says...
  

You can use more then one [][] using a proxy object:  This is something 
I posted before.  You'll need to work it into your own problem.

Most of the overhead would be optimised away.

    

Well, but that's not more than a workaround.

The problem now is what to do, if i
need both, a two-parameter operator (for matrix-like access) _and_ a
one-parameter operator (for vector-like access) in one class? I cannot use the
[]-operator for both. And _most_ of the overhead is not _all_, and that's sth I
don't like, because speed is an important factor in my case.

Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
  

Using the way I suggested is quite powerful because you can control each dimension of the array ie: A[x].length = 10; A[x][y].length = 10; Also if you want to use the array for more then one thing, simply create a new class to do it and then call it by method using something like this: A.reverse[x][y] ... -- -Anderson: http://badmama.com.au/~anderson/
May 09 2004
parent Frank Fischer <fifr hrz.tu-chemnitz.de> writes:
On 2004-05-09, J Anderson <REMOVEanderson badmama.com.au> wrote:
The problem now is what to do, if i
need both, a two-parameter operator (for matrix-like access) _and_ a
one-parameter operator (for vector-like access) in one class? I cannot use the
[]-operator for both. And _most_ of the overhead is not _all_, and that's sth I
don't like, because speed is an important factor in my case.

Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
  

Using the way I suggested is quite powerful because you can control each dimension of the array ie: A[x].length = 10; A[x][y].length = 10; Also if you want to use the array for more then one thing, simply create a new class to do it and then call it by method using something like this: A.reverse[x][y] ...

matrices in the mathematical sense. So there's no need for controlling each dimension of subarrays. And I think it's strange to access elements of a matrix like this: A.matrix[i][j] A.vector[i] ... Wouldn't it be nicer to do it that way: A(i,j) and A(i) Of course, returning pointers could be a way out (as mentioned in another posting by someone), but I think that's not the way someone using this matrix-class would expect. And as always, something unexpected is a potential source of trouble.
May 09 2004
prev sibling parent reply Juan C <Juan_member pathlink.com> writes:
<snip>
m.at(1,1) = 1.0;
/* or with operators: */
m(1,1) = 1.0;

M m = new M(1.0); would be clearer, no?
May 08 2004
parent Frank Fischer <fifr hrz.tu-chemnitz.de> writes:
On 2004-05-09, Juan C <Juan_member pathlink.com> wrote:
<snip>
m.at(1,1) = 1.0;
/* or with operators: */
m(1,1) = 1.0;

M m = new M(1.0); would be clearer, no?

of a new object.
May 09 2004