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








Ben Hinkle <bhinkle4 juno.com>