Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
May 12, 2005 Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Hi, what exactly are the objections against simple inheritance mechanisms (without virtual functions, RTTI or something like that) for structs? That would make it easy to base a struct upon an existing one without the need to rewrite/delegate existing functions. Has this been a discussion subject before? Thanks uwe |
May 12, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uwe Salomon | "Has this been a discussion subject before?" I am pretty sure - yes. If I need two structures to have common members then I am using mixins for defininig common parts of such structures. Well, of course it is a palliative , but mostly works. Sample: template BrickT() { ushort type; short posx; short posy; ushort dimx; ushort dimy; short ascent; rect place() { return rect( pos, dim ); } point pos() { return point( posx, posy); } size dim() { return size( dimx, dimy); } } align(2) struct Brick // non breakable layout element { mixin BrickT; } align(2) struct Word // word or space { mixin BrickT; ushort length; // total length in wchars // wchars are here.... } Andrew. "Uwe Salomon" <post@uwesalomon.de> wrote in message news:op.sqnsqpu96yjbe6@sandmann.maerchenwald.net... > Hi, > > what exactly are the objections against simple inheritance mechanisms (without virtual functions, RTTI or something like that) for structs? That would make it easy to base a struct upon an existing one without the need to rewrite/delegate existing functions. Has this been a discussion subject before? > > Thanks > uwe |
May 12, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uwe Salomon | Andrew's use of mixins is one good method. Another is to use inner structs and aliases. For example: # # struct Size { # uint width, height; # } # # struct Point { # uint x, y; # } # # struct Rect { # Size size; # alias size.width width; # alias size.height height; # # Point point; # alias point.x x; # alias point.y y; # } # The one thing that is missing from either method, and is therefore the one thing I personally would like to see struct-inheritance for, is hierarchial type resolution. In other words, I couldn't declare a function to take a parameter of type Size and then pass it a Rect. I think the real stopping point probably boils down to virtual functions, but there might be another way? -- Chris Sauls |
May 12, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Sauls | > In other words, I couldn't declare a function to take a parameter of type Size and then pass it a Rect. I
> think the real stopping point probably boils down to virtual functions, but there might be another way?
If i needed virtual functions and all that stuff, i would use a class. I think it is a good idea that structs don't have that ballast. All i am talking of is a simple way to base a struct upon another struct. If it were just for three member variables and a function, i would use aliases. But i have structs with a lot of functions, 30 or 50 or so. They are structs because they *need* value semantics. I don't want to write aliases for all these functions, for all these structs. And using mixins is just so clumsy with 2000 lines of code in them, and not very clear style either.
uwe
|
May 12, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uwe Salomon | "Uwe Salomon" <post@uwesalomon.de> wrote in message news:op.sqoid3tj6yjbe6@sandmann.maerchenwald.net... >> In other words, I couldn't declare a function to take a parameter of >> type Size and then pass it a Rect. I >> think the real stopping point probably boils down to virtual functions, >> but there might be another way? > > If i needed virtual functions and all that stuff, i would use a class. I think it is a good idea that structs don't have that ballast. All i am talking of is a simple way to base a struct upon another struct. If it were just for three member variables and a function, i would use aliases. But i have structs with a lot of functions, 30 or 50 or so. They are structs because they *need* value semantics. I don't want to write aliases for all these functions, for all these structs. And using mixins is just so clumsy with 2000 lines of code in them, and not very clear style either. > > uwe I'm curious about the context - can you describe the problem in more detail? That's a pretty honkin' struct. |
May 13, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | >> If i needed virtual functions and all that stuff, i would use a class. I
>> think it is a good idea that structs don't have that ballast. All i am
>> talking of is a simple way to base a struct upon another struct. If it
>> were just for three member variables and a function, i would use aliases.
>> But i have structs with a lot of functions, 30 or 50 or so. They are
>> structs because they *need* value semantics. I don't want to write aliases
>> for all these functions, for all these structs. And using mixins is just
>> so clumsy with 2000 lines of code in them, and not very clear style
>> either.
>
> I'm curious about the context - can you describe the problem in more detail?
> That's a pretty honkin' struct.
:) Well, the idea behind it is just the same as with MinTL: Containers should be structs to reduce overhead and, more important, to gain value semantics. That makes containers in containers possible:
Map!(char[], Vector!(int)) funnyMap;
If Vector was a template class, all the vectors would need initialization (-- not sure if this is correct grammar, i have problems with the conjunctive... --), because they are null by default. That fact made all my containers (Vector, List, LinkedList, Map) structs, just like yours in MinTL. They are quite big, as you can imagine (lots of convenience functions and algorithms, sorting, etc.). Now if i want to write a Queue for example, that's just a special LinkedList (though that's not the best way to implement a queue, yes):
struct Queue(T) : LinkedList!(T)
{
public void enqueue(T value)
{
append(value);
}
// Or better, with aliases:
alias takeLast dequeue;
}
That gives me a nice queue, with minimal effort and all the good things from LinkedList. This could be realized with the technique you used, yes (enqueue and dequeue in LinkedList, and Queue is just an alias), but look at the following example:
struct StringList : public List!(char[])
// Actually, char[] would be a struct String.
{
public char[] join()
{
// Not bad, but could be implemented a bit better:
size_t fullLength = 0;
foreach (char[] str; *this)
fullLength += str.length;
char[] result;
result.length = fullLength;
fullLength = 0;
foreach (char[] str; *this)
{
result[fullLength .. (fullLength + str.length)] = str[];
fullLength += str.length;
}
}
// Other functions, like join(char[] sep) ...
}
I cannot program that functionality into List, neither do i want to reimplement List!(char[]). All i have left is extracting the List implementation into a mixin, and inserting this mixin into List and StringList (or mess around with partial specialization, even worse). Though that is possible, it is not very straightforward and clear style. The above is such a simple idea, but to realize it i need to come up with complex templates, mixins and whatever is possible in D. That's why i asked for struct inheritance.
But, as it is unlikely that Walter changes it, are there some clever solutions for the StringList that come to your mind? As i see it, it is not possible to imitate the behaviour of QStringList here... :(
Ciao
uwe
|
May 13, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uwe Salomon | "Uwe Salomon" <post@uwesalomon.de> wrote in message news:op.sqppz5wb6yjbe6@sandmann.maerchenwald.net... >>> If i needed virtual functions and all that stuff, i would use a class. I >>> think it is a good idea that structs don't have that ballast. All i am >>> talking of is a simple way to base a struct upon another struct. If it >>> were just for three member variables and a function, i would use >>> aliases. >>> But i have structs with a lot of functions, 30 or 50 or so. They are >>> structs because they *need* value semantics. I don't want to write >>> aliases >>> for all these functions, for all these structs. And using mixins is just >>> so clumsy with 2000 lines of code in them, and not very clear style >>> either. >> >> I'm curious about the context - can you describe the problem in more >> detail? >> That's a pretty honkin' struct. > > :) Well, the idea behind it is just the same as with MinTL: Containers should be structs to reduce overhead and, more important, to gain value semantics. That makes containers in containers possible: > > Map!(char[], Vector!(int)) funnyMap; > > If Vector was a template class, all the vectors would need initialization (-- not sure if this is correct grammar, i have problems with the conjunctive... --), because they are null by default. That fact made all my containers (Vector, List, LinkedList, Map) structs, just like yours in MinTL. They are quite big, as you can imagine (lots of convenience functions and algorithms, sorting, etc.). ok, that makes sense to me now. I actually thought you had wanted to inherit data members and not function members. You are right that it would be useful to allow "virtual functions" for structs. I guess > Now if i want to write a Queue for example, that's just a special LinkedList (though that's not the best way to implement a queue, yes): > > struct Queue(T) : LinkedList!(T) > { > public void enqueue(T value) > { > append(value); > } > > // Or better, with aliases: > alias takeLast dequeue; hmm - MinTL has "removeLast"... I think I actually like "takeLast" better. > } > > That gives me a nice queue, with minimal effort and all the good things from LinkedList. This could be realized with the technique you used, yes (enqueue and dequeue in LinkedList, and Queue is just an alias), but look at the following example: > > struct StringList : public List!(char[]) > // Actually, char[] would be a struct String. > { > public char[] join() > { > // Not bad, but could be implemented a bit better: > size_t fullLength = 0; > foreach (char[] str; *this) > fullLength += str.length; > > char[] result; > result.length = fullLength; > fullLength = 0; > foreach (char[] str; *this) > { > result[fullLength .. (fullLength + str.length)] = str[]; > fullLength += str.length; > } > } > > // Other functions, like join(char[] sep) ... > } Thinking off the top of my head to write join() today you'd have to put it on the top level instead, correct? Generalizing it to join any container of lists might not be a bad things, though. If the container supports foreach one could write template join(T, Container) { T[] join(Container c){ size_t n=0; foreach(T[] val; c) { n += val.length; } T[] res = new T[n]; n = 0; foreach(T[] val; c) { res[n .. n+val.length] = val[]; n+= val.length; } return res; } } and then call it like alias List!(char[]) StringList; alias join!(char,StringList) strjoin; // for simpler user code StringList strs; ... char[] together = strjoin(strs); ArrayList!(int[]) ints; ... int[] together2 = join!(int,typeof(ints))(ints); I might include some handy things like that into MinTL. > I cannot program that functionality into List, neither do i want to reimplement List!(char[]). All i have left is extracting the List implementation into a mixin, and inserting this mixin into List and StringList (or mess around with partial specialization, even worse). Though that is possible, it is not very straightforward and clear style. The above is such a simple idea, but to realize it i need to come up with complex templates, mixins and whatever is possible in D. That's why i asked for struct inheritance. I don't completely agree that mixins are not straightforward or have a clear style (if I understand your position). It's pretty much the same to me if a type gets features from inheritance or from a mixin. The difference is only syntactic, really: struct Foo : Bar { } struct Foo { mixin Bar } unless you want to allow Foos to be implicitly cast to Bars (mixins wouldn't be able to do that). > But, as it is unlikely that Walter changes it, are there some clever solutions for the StringList that come to your mind? As i see it, it is not possible to imitate the behaviour of QStringList here... :( > > Ciao > uwe |
May 13, 2005 Re: Inheritance for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | >> // Or better, with aliases: >> alias takeLast dequeue; > > hmm - MinTL has "removeLast"... I think I actually like "takeLast" better. :) I have both of 'em, removeLast only removes, takeLast removes and returns it. > char[] together = strjoin(strs); I have to admit that this is really neat. :) > It's pretty much the same to me if a type gets features from inheritance or from a mixin. Perhaps i will go this way, then. Or make it global. Ah, well, D is not C++, and Indigo is not Qt. Thanks & ciao uwe |
Copyright © 1999-2021 by the D Language Foundation