D - language limitations?
- Norbert Nemec (103/103) Apr 24 2004 Hi there,
- Ben Hinkle (5/12) Apr 24 2004 There's a nifty technique using opCall to write struct "constructors". I
Hi there, I just tried to scribble an implementation of multidimensional arrays. (See below). As you can see, I chose "struct" over "class" for the Array, since Array itself is basically an extended pointer to the array data. Putting it on the heap as an object of a class and handling a reference to it would mean additional overhead and strange semantics. Now there are a few limitations I could not overcome yet: * structs cannot have a constructor and seem generally rather limited. I do not propose to add everything to a struct that a class has (like that C++-stupidity of struct vs. class) but I would still like to think of them as "lightweight" classes. (I.e. stored on the stack, no virtual members, but full encapsulation etc.) * array literals are badly missing - or, even better - "array expressions", that are not limited to constant entries. * lvalues (i.e. references) as return-values of functions would help avoid duplicating code and give more flexibility. Any ideas? Ciao, Nobbi --------------------------------------- alias size_t idx_t; alias ptrdiff_t stride_t; struct slice_t { idx min; idx max; // actually max + 1 stride_t stride; }; struct Array(T,uint DIM) { private T* data; // not a T[] because stride might be negative private idx_t range[DIM]; private stride_t stride[DIM]; void constructor(idx_t[DIM] r) { range[] = r[]; uint size = 1; for(uint d=DIM;d--;) { stride[d] = size; size *= range[d]; }; data = new T[size]; }; private T* ptr(idx_t[DIM] i) in { foreach(uint d,idx_t id;i) { assert(id < range[d]); }; } body { int offset = 0; foreach(uint d,idx_t id;i) { offset += id*stride[d]; }; return &data[offset]; }; T opIndex(idx_t[DIM] i) { return *ptr(i); }; T opIndex(idx_t[DIM] i, T value) { return *ptr(i) = value; }; .Array!(T,DIM) slice(slice_t[DIM] sl) in { foreach(uint d,slice_t s;sl) { assert(s.min <= s.max); assert(s.max <= range[d]); assert(s.stride > 0); // negative strides not yet implemented }; } body { .Array!(T,DIM) res; idx_t[DIM] min_idx; foreach(uint d,slice_t s;sl) { res.range[d] = (s.max-s.min + s.stride - 1) / s.stride; res.stride[d] = stride[d] * s.stride; min_idx[d] = s.min; }; res.data = ptr(min_idx); return res; }; }; int main() { static idx_t[2] range = [3,4]; Array!(real,2) a; a.constructor(range); static idx_t[2] a_idx = [2,1]; a[a_idx] = 1.5; static slice_t[2] myslice = [{min:0,max:3,stride:2}, {min:1,max:4,stride:2}]; Array!(real,2) b = a.slice(myslice); static idx_t[2] b_idx = [1,0]; b[b_idx] = b[b_idx] * 3; printf("%Lg\n",a[a_idx]); // should show 4.5 return 0; }; --------------------------------------
Apr 24 2004
Now there are a few limitations I could not overcome yet: * structs cannot have a constructor and seem generally rather limited. I do not propose to add everything to a struct that a class has (like that C++-stupidity of struct vs. class) but I would still like to think of them as "lightweight" classes. (I.e. stored on the stack, no virtual members, but full encapsulation etc.)There's a nifty technique using opCall to write struct "constructors". I haven't tried using it with templates but you might give it a try. I added an example of this technique to dsource: http://www.dsource.org/tutorials/index.php?show_example=70 -Ben
Apr 24 2004