digitalmars.D - why cant structs have base structs
- Regan Heath <regan netwin.co.nz> Jun 23 2004
- Norbert Nemec <Norbert.Nemec gmx.de> Jun 23 2004
- Regan Heath <regan netwin.co.nz> Jun 23 2004
- Daniel Horn <hellcatv hotmail.com> Jun 23 2004
- Norbert Nemec <Norbert.Nemec gmx.de> Jun 23 2004
- Jan-Eric Duden <jeduden whisset.com> Jun 24 2004
- Norbert Nemec <Norbert.Nemec gmx.de> Jun 24 2004
- Jan-Eric Duden <jeduden whisset.com> Jun 24 2004
- Daniel Horn <hellcatv hotmail.com> Jun 24 2004
- "Walter" <newshound digitalmars.com> Jul 01 2004
- "Ivan Senji" <ivan.senji public.srce.hr> Jul 01 2004
- Regan Heath <regan netwin.co.nz> Jul 01 2004
- "Ivan Senji" <ivan.senji public.srce.hr> Jul 02 2004
- Regan Heath <regan netwin.co.nz> Jul 02 2004
- "Ivan Senji" <ivan.senji public.srce.hr> Jul 02 2004
- Regan Heath <regan netwin.co.nz> Jul 01 2004
- Regan Heath <regan netwin.co.nz> Jul 01 2004
- Derek Parnell <derek psych.ward> Jul 01 2004
- Regan Heath <regan netwin.co.nz> Jul 01 2004
- Russ Lewis <spamhole-2001-07-16 deming-os.org> Jun 24 2004
- Jan-Eric Duden <jeduden whisset.com> Jun 24 2004
- "Matthew" <admin stlsoft.dot.dot.dot.dot.org> Jun 24 2004
- Brian <Brian_member pathlink.com> Jul 01 2004
- Regan Heath <regan netwin.co.nz> Jul 01 2004
- Regan Heath <regan netwin.co.nz> Jul 01 2004
This:
struct a {
}
struct b : a {
}
is not valid, the spec does not seem to allow it, why not?
Regan
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 23 2004
Regan Heath wrote:This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not?
My guess: Structs cannot have virtual functions (adding that feature would mean overhead which should be avoided for structs) Without virtual functions, the behavior of struct-inheritance would be strangely different from the behavior of class-inheritance, where every public function is implicitly virtual. Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
Jun 23 2004
On Thu, 24 Jun 2004 07:52:11 +0200, Norbert Nemec <Norbert.Nemec gmx.de> wrote:Regan Heath wrote:This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not?
My guess: Structs cannot have virtual functions (adding that feature would mean overhead which should be avoided for structs)
Agreed.Without virtual functions, the behavior of struct-inheritance would be strangely different from the behavior of class-inheritance, where every public function is implicitly virtual.
Different, yes. Strange .. not so long as it's documented.Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
Ok. You've convinced me. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 23 2004
Regan Heath wrote:On Thu, 24 Jun 2004 07:52:11 +0200, Norbert Nemec <Norbert.Nemec gmx.de> wrote:Regan Heath wrote:This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not?
My guess: Structs cannot have virtual functions (adding that feature would mean overhead which should be avoided for structs)
Agreed.Without virtual functions, the behavior of struct-inheritance would be strangely different from the behavior of class-inheritance, where every public function is implicitly virtual.
Different, yes. Strange .. not so long as it's documented.Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
Ok. You've convinced me.
took a thing and didn't want to use templates struct Thing{ float amt; } struct SuperThing :Thing { char[] name; } now it's not just a matter of saving typing, but actually having it do all the things you could with thing. in C you'd use an anonymous union to accomplish this-- is that also possible in D? struct Thing { float amt; }; struct SuperThing { union { float amt; Thing thing; }; char[] name; };Regan
Jun 23 2004
Daniel Horn wrote:Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
Ok. You've convinced me.
took a thing and didn't want to use templates
That's just what I mean with "polymorphism" - as mentioned: polymorphism demands for virtual functions, and these mean overhead. If you want polymorphism, use classes. (There is no point in using polymorphism without handling the objects by reference, anyway.)
Jun 23 2004
Norbert Nemec wrote:Daniel Horn wrote:Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
Ok. You've convinced me.
but what if you wanted to pass a SuperThing into a function that only took a thing and didn't want to use templates
That's just what I mean with "polymorphism" - as mentioned: polymorphism demands for virtual functions, and these mean overhead. If you want polymorphism, use classes. (There is no point in using polymorphism without handling the objects by reference, anyway.)
in C++ i could do the following: struct MyPolyStruct { int type; }; struct A : public MyPolyStruct { int a; } struct C : public MyPolyStruct { float c[1000]; } void bla(MyPolyStruct* p) { switch(p->type) { //do stuff } } I still need to do a cast to get the subclass data, but this is a bit "type-safier" than doing this in D: template MyPolyType { int type; }; struct Base { mixin MyPolyType; } struct A { mixin MyPolyType; int a; } struct C { mixin MyPolyType; float c[1000]; } int bla(void* p) // need to use void ptr here { switch((cast(Base)p).type) { //do stuff } } some times you need to do this stuff, f.e. when you implement functions that work on binary formats. Standard polymorphism doesn't help here at all. Are there better solutions for doing this kind of stuff in D? Note that using unions doesn't really help ( without having memory overhead): struct MyPolyStruct { int type; union { int a; float c[1000]; } data; }; Jan-Eric
Jun 24 2004
Jan-Eric Duden wrote:Are there better solutions for doing this kind of stuff in D?
Use classes! The only reason to use struct instead of class is, if you want value-semantics (as opposed to reference semantics which are the only available behaviour for classes in D) Polymorphism is generally only possible when handling references. (Since the size of an inheriting class is not known, it cannot be passed by value) Your C++ example uses a pointer to a struct. In D, you should simply use a class for that.
Jun 24 2004
Norbert Nemec wrote:Jan-Eric Duden wrote:Are there better solutions for doing this kind of stuff in D?
Use classes! The only reason to use struct instead of class is, if you want value-semantics (as opposed to reference semantics which are the only available behaviour for classes in D) Polymorphism is generally only possible when handling references. (Since the size of an inheriting class is not known, it cannot be passed by value) Your C++ example uses a pointer to a struct. In D, you should simply use a class for that.
exact binary layout. With classes you have memory overhead that is too large in some cases.Custom allocators won't help all the time. A small example: I have a file with 1,000,000 objects. all objects have the same size. I need to do some sorting and other stuff. the object size is 16 bytes. 16 MB is not too much for my memory requirements. I allocate just one chunk of memory. read all the objects into that chunk. hold a struct pointer on that chunk. easy and efficient. If I have to do that with class objects... I get gc overhead for 1 million objects, 1 million times a monitor, 1 million times a virtual function table pointer, ... 1 million new calls, 1 million read calls. In that case structs a just better. Jan-Eric
Jun 24 2004
Norbert Nemec wrote:Jan-Eric Duden wrote:Are there better solutions for doing this kind of stuff in D?
Use classes!
important--esp if you're doing something like a number sort of class or a vectorThe only reason to use struct instead of class is, if you want value-semantics (as opposed to reference semantics which are the only available behaviour for classes in D) Polymorphism is generally only possible when handling references. (Since the size of an inheriting class is not known, it cannot be passed by value) Your C++ example uses a pointer to a struct. In D, you should simply use a class for that.
Jun 24 2004
You can do the following:
struct A { ... }
struct B
{
A a;
... more members ...
}
Jul 01 2004
"Walter" <newshound digitalmars.com> wrote in message news:cc0hlu$9gv$2 digitaldaemon.com...You can do the following: struct A { ... } struct B { A a; ... more members ... }
Or even (maybe) better: struct A() { } struct B { mixin A!(); // ... more members ... }
Jul 01 2004
On Thu, 1 Jul 2004 14:12:37 +0200, Ivan Senji <ivan.senji public.srce.hr> wrote:"Walter" <newshound digitalmars.com> wrote in message news:cc0hlu$9gv$2 digitaldaemon.com...You can do the following: struct A { ... } struct B { A a; ... more members ... }
Or even (maybe) better: struct A() { } struct B { mixin A!(); // ... more members ... }
Nope: mixin A!() A is not a template Besides which you cannot use a mixin to add private members. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 01 2004
"Regan Heath" <regan netwin.co.nz> wrote in message news:opsahbksx25a2sq9 digitalmars.com...On Thu, 1 Jul 2004 14:12:37 +0200, Ivan Senji <ivan.senji public.srce.hr> wrote:"Walter" <newshound digitalmars.com> wrote in message news:cc0hlu$9gv$2 digitaldaemon.com...You can do the following: struct A { ... } struct B { A a; ... more members ... }
Or even (maybe) better: struct A() { } struct B { mixin A!(); // ... more members ... }
Nope: mixin A!() A is not a template
I am a real idiot for not trying to add member variables.Besides which you cannot use a mixin to add private members.
I tried this and it seems that i can template A() { int x,y; } struct B { private mixin A!(); float a,b; } And i get a nice message "struct B A!().x is private" B b; b.a=3; b.x=4;//<-error here but ofcourse it has to be in another module to manifest this behaviour!Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 02 2004
On Fri, 2 Jul 2004 09:06:25 +0200, Ivan Senji <ivan.senji public.srce.hr> wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opsahbksx25a2sq9 digitalmars.com...On Thu, 1 Jul 2004 14:12:37 +0200, Ivan Senji <ivan.senji public.srce.hr> wrote:"Walter" <newshound digitalmars.com> wrote in message news:cc0hlu$9gv$2 digitaldaemon.com...You can do the following: struct A { ... } struct B { A a; ... more members ... }
Or even (maybe) better: struct A() { } struct B { mixin A!(); // ... more members ... }
Nope: mixin A!() A is not a template
I am a real idiot for not trying to add member variables.Besides which you cannot use a mixin to add private members.
I tried this and it seems that i can template A() { int x,y; } struct B { private mixin A!(); float a,b; } And i get a nice message "struct B A!().x is private" B b; b.a=3; b.x=4;//<-error here but ofcourse it has to be in another module to manifest this behaviour!
Yes you can do that, what I actually mean't to say was, you cannot go... template A() { public: void foo() { bar(); } private: int a; } struct B { mixin A; void bar() { a = 5; } } 'int a' is private to mixin A and not accessable at all to B. But, now that I think about it, were I allowed to go... struct A { public: void foo() { bar(); } private: int a; } struct B : A { mixin A; void bar() { a = 5; } } it wouldn't work either as (I assume) A's privates would not be accessable to B (using standard C++ class inheritance etc). So my workaround to make the private section protected is probably the correct way to do it anyway. I'll go put my head in a paper bag now :) (not plastic - cos that's dangerous) Regan.Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 02 2004
"Regan Heath" <regan netwin.co.nz> wrote in message news:opsaigb8o15a2sq9 digitalmars.com...On Fri, 2 Jul 2004 09:06:25 +0200, Ivan Senji <ivan.senji public.srce.hr> wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opsahbksx25a2sq9 digitalmars.com...
Yes you can do that, what I actually mean't to say was, you cannot go...
I finally understand what is troubling you. I read yout previous posts about this but didn't have any time to try it out.template A() { public: void foo() { bar(); } private: int a; } struct B { mixin A; void bar() { a = 5; } } 'int a' is private to mixin A and not accessable at all to B. But, now that I think about it, were I allowed to go... struct A { public: void foo() { bar(); } private: int a; } struct B : A { mixin A; void bar() { a = 5; } } it wouldn't work either as (I assume) A's privates would not be accessable to B (using standard C++ class inheritance etc).
Yes i also think you are right, mixin has its own scope and decides what to give access to.So my workaround to make the private section protected is probably the correct way to do it anyway.
Conclusion: your workaround isn't a workaround at all, but the way it should work.I'll go put my head in a paper bag now :) (not plastic - cos that's dangerous)
:)Regan.Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 02 2004
On Thu, 1 Jul 2004 01:11:15 -0700, Walter <newshound digitalmars.com> wrote:You can do the following: struct A { ... } struct B { A a; ... more members ... }
That's not the same. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 01 2004
On Thu, 1 Jul 2004 01:11:15 -0700, Walter <newshound digitalmars.com> wrote:You can do the following: struct A { ... } struct B { A a; ... more members ... }
Should this work? --[test.d]-- struct A { int aaa; int bbb; } struct B { A a_instance; alias a_instance.aaa aaa; alias a_instance.bbb bbb; } void main() { B b; b.aaa = 5; b.bbb = 6; } Cos it gives: test.d(7): identifier 'aaa' of 'a_instance.aaa' is not defined Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 01 2004
On Fri, 02 Jul 2004 16:12:07 +1200, Regan Heath wrote:struct A { int aaa; int bbb; } struct B { A a_instance; alias a_instance.aaa aaa; alias a_instance.bbb bbb; } void main() { B b; b.aaa = 5; b.bbb = 6; }
This works ... #struct A { # int aaa; # int bbb; #} #struct B { # A a_instance; # alias A.aaa aaa; # alias A.bbb bbb; #} # #void main() { # B b; # # b.aaa = 5; # b.bbb = 6; #} But doesn't help if you have two or more instances of A inside B. -- Derek Melbourne, Australia 2/Jul/04 2:19:58 PM
Jul 01 2004
On Fri, 2 Jul 2004 14:27:17 +1000, Derek Parnell <derek psych.ward> wrote:On Fri, 02 Jul 2004 16:12:07 +1200, Regan Heath wrote:struct A { int aaa; int bbb; } struct B { A a_instance; alias a_instance.aaa aaa; alias a_instance.bbb bbb; } void main() { B b; b.aaa = 5; b.bbb = 6; }
This works ... #struct A { # int aaa; # int bbb; #} #struct B { # A a_instance; # alias A.aaa aaa; # alias A.bbb bbb; #} # #void main() { # B b; # # b.aaa = 5; # b.bbb = 6; #} But doesn't help if you have two or more instances of A inside B.
Thanks.. I still have not got the hang of aliases like this. :) I am trying to emulate having a base struct (like a base class only no virtual functions etc), so there will not be more than one instance of A inside B. This workaround isn't too bad so long as there aren't too many members in the 'base' struct. You can go another level deep but it requires some copy/pasting... struct A { int var1; int var2; } struct B { A a; alias A.var1 var1; alias A.var2 var2; int var3; int var4; } struct C { B b; alias B.var1 var1; alias B.var2 var2; alias B.var3 var3; alias B.var4 var4; } void main() { C c; c.var1 = 5; c.var2 = 6; c.var3 = 7; c.var4 = 8; } Walter: it would be nice if the above could be achieved with struct A { int var1; int var2; } struct B : A { int var3; int var4; } struct C : B { } Much simpler! Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 01 2004
Daniel Horn wrote:struct Thing{ float amt; } struct SuperThing :Thing { char[] name; } now it's not just a matter of saving typing, but actually having it do all the things you could with thing. in C you'd use an anonymous union to accomplish this-- is that also possible in D? struct Thing { float amt; }; struct SuperThing { union { float amt; Thing thing; }; char[] name; };
What you code here should work...though I don't know why you wouldn't just include the Thing directly. The union is unnecessary: struct SuperThing { Thing thing; char[] name; }; If you want to implement something that looks more like C++ inheritance, you can do it with properties: struct SuperThing { Thing super; float amt() { return super.amt; } float amt(float f) { return super.amt = f; } char[] name; }; You don't get implicit casting, but that's not too hard: Thing* castThing(SuperThing* s) { return s.super; } Likewise, you can even implement constructors and virtual functions by hand if you want; but you have to run the constructor by hand, and make sure it initialized the virtual functions allright: struct Thing { struct { int delegate() foo; } vtbl; void Constructor() { this.vtbl.foo = &this.foo; } int foo() { ...do stuff... } float amt; } struct SuperThing { Thing super; float amt() { return super.amt; } float amt(float f) { return super.amt = f; } void Constructor() { super.Constructor(); super.vtbl.foo = &this.foo; } int foo() { ...do stuff... } char[] name; } Thing thing1; thing1.Constructor(); SuperThing thing2; thing2.Constructor(); Thing *ptr1; Thing *ptr2; ptr1 = &thing1; ptr2 = castThing(&thing2); ptr1.vtbl.foo(); // runs Thing.foo() ptr2.vtbl.foo(); // runs SuperThing.foo()
Jun 24 2004
Russ Lewis wrote:Daniel Horn wrote:struct Thing{ float amt; } struct SuperThing :Thing { char[] name; } now it's not just a matter of saving typing, but actually having it do all the things you could with thing. in C you'd use an anonymous union to accomplish this-- is that also possible in D? struct Thing { float amt; }; struct SuperThing { union { float amt; Thing thing; }; char[] name; };
What you code here should work...though I don't know why you wouldn't just include the Thing directly. The union is unnecessary: struct SuperThing { Thing thing; char[] name; }; If you want to implement something that looks more like C++ inheritance, you can do it with properties: struct SuperThing { Thing super; float amt() { return super.amt; } float amt(float f) { return super.amt = f; } char[] name; }; You don't get implicit casting, but that's not too hard: Thing* castThing(SuperThing* s) { return s.super; } Likewise, you can even implement constructors and virtual functions by hand if you want; but you have to run the constructor by hand, and make sure it initialized the virtual functions allright: struct Thing { struct { int delegate() foo; } vtbl; void Constructor() { this.vtbl.foo = &this.foo; } int foo() { ...do stuff... } float amt; } struct SuperThing { Thing super; float amt() { return super.amt; } float amt(float f) { return super.amt = f; } void Constructor() { super.Constructor(); super.vtbl.foo = &this.foo; } int foo() { ...do stuff... } char[] name; } Thing thing1; thing1.Constructor(); SuperThing thing2; thing2.Constructor(); Thing *ptr1; Thing *ptr2; ptr1 = &thing1; ptr2 = castThing(&thing2); ptr1.vtbl.foo(); // runs Thing.foo() ptr2.vtbl.foo(); // runs SuperThing.foo()
it's not too much work for doing this kind of rare stuff. with mixins you can do this, too: struct Thing { // stuff }: template BaseStruct { Thing myThing; Thing* castThing() { return &myThing; } }; struct A { mixin BaseStruct; int stuffint; };
Jun 24 2004
"Norbert Nemec" <Norbert.Nemec gmx.de> wrote in message news:cbdq61$2u6v$1 digitaldaemon.com...Regan Heath wrote:This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not?
My guess: Structs cannot have virtual functions (adding that feature would mean overhead which should be avoided for structs) Without virtual functions, the behavior of struct-inheritance would be strangely different from the behavior of class-inheritance, where every public function is implicitly virtual. Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
Very nice point! I knew there was a point to trawling the posts tonight. Thanks for that. :)
Jun 24 2004
In article <opr92xf8ba5a2sq9 digitalmars.com>, Regan Heath says...This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
It isn't allowed because structs in d are c style structs not c++ style stucts. In C the struct makes a data aggregate. For C++ this is not the case. The struct key word is equivalent to class foo{ public:} by that I mean it creates a class which defaults to public instead of private. So it has all of that over head you wish to avoid.
Jul 01 2004
On Thu, 1 Jul 2004 15:15:36 +0000 (UTC), Brian <Brian_member pathlink.com> wrote:In article <opr92xf8ba5a2sq9 digitalmars.com>, Regan Heath says...This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
It isn't allowed because structs in d are c style structs not c++ style stucts.
I know. Currently, they are...In C the struct makes a data aggregate. For C++ this is not the case. The struct key word is equivalent to class foo{ public:} by that I mean it creates a class which defaults to public instead of private. So it has all of that over head you wish to avoid.
The overhead comes when it's implemented as you suggest. You can implement structs with inheritance and without virtual functions to remove all that overhead. similar to: struct A { } struct B { mixin A; } however there are 2 problems with this soln. 1. it does not work, you cannot mixin a struct. 2. you cannot use a mixin to add 'private' members. What I want is to be able to say: struct A { virtual void bar(); private: void foo(); } struct B : A { void bar() { foo(); } } Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 01 2004
On Fri, 02 Jul 2004 10:07:51 +1200, Regan Heath <regan netwin.co.nz> wrote:On Thu, 1 Jul 2004 15:15:36 +0000 (UTC), Brian <Brian_member pathlink.com> wrote:In article <opr92xf8ba5a2sq9 digitalmars.com>, Regan Heath says...This: struct a { } struct b : a { } is not valid, the spec does not seem to allow it, why not? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
It isn't allowed because structs in d are c style structs not c++ style stucts.
I know. Currently, they are...In C the struct makes a data aggregate. For C++ this is not the case. The struct key word is equivalent to class foo{ public:} by that I mean it creates a class which defaults to public instead of private. So it has all of that over head you wish to avoid.
The overhead comes when it's implemented as you suggest. You can implement structs with inheritance and without virtual functions to remove all that overhead. similar to: struct A { } struct B { mixin A; } however there are 2 problems with this soln. 1. it does not work, you cannot mixin a struct. 2. you cannot use a mixin to add 'private' members. What I want is to be able to say: struct A { virtual void bar(); private: void foo(); } struct B : A { void bar() { foo(); } }
Small correction, there should be a body in the void foo() function in struct A. My current workaround is to make A a template, and to make foo protected rather than private. Regards, Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 01 2004









Jan-Eric Duden <jeduden whisset.com> 