digitalmars.D - why cant structs have base structs
- Regan Heath (9/9) Jun 23 2004 This:
- Norbert Nemec (10/19) Jun 23 2004 My guess:
- Regan Heath (8/27) Jun 23 2004 Agreed.
- Daniel Horn (23/63) Jun 23 2004 but what if you wanted to pass a SuperThing into a function that only
- Norbert Nemec (5/14) Jun 23 2004 That's just what I mean with "polymorphism" - as mentioned: polymorphism
- Jan-Eric Duden (64/84) Jun 24 2004 "polymorphism" does not demand for virtual functions by default.
- Norbert Nemec (9/10) Jun 24 2004 Use classes!
- Jan-Eric Duden (14/31) Jun 24 2004 You can't use classes in some cases. With classes you can't model an
- Daniel Horn (4/21) Jun 24 2004 classes are on the heap, structs can be on the stack--this is
- Walter (7/7) Jul 01 2004 You can do the following:
- Ivan Senji (9/16) Jul 01 2004 Or even (maybe) better:
- Regan Heath (7/27) Jul 01 2004 Nope: mixin A!() A is not a template
- Ivan Senji (19/50) Jul 02 2004 I am a real idiot for not trying to add member variables.
- Regan Heath (44/100) Jul 02 2004 Yes you can do that, what I actually mean't to say was, you cannot go...
- Ivan Senji (10/64) Jul 02 2004 I finally understand what is troubling you. I read yout previous posts a...
- Regan Heath (6/13) Jul 01 2004 That's not the same.
- Regan Heath (24/31) Jul 01 2004 Should this work?
- Derek Parnell (23/39) Jul 01 2004 This works ...
- Regan Heath (49/84) Jul 01 2004 Thanks.. I still have not got the hang of aliases like this. :)
- Russ Lewis (49/72) Jun 24 2004 What you code here should work...though I don't know why you wouldn't
- Jan-Eric Duden (21/117) Jun 24 2004 that looks like a reasonable solution.
- Matthew (4/23) Jun 24 2004 Very nice point! I knew there was a point to trawling the posts tonight.
- Brian (6/15) Jul 01 2004 It isn't allowed because structs in d are c style structs not c++ style ...
- Regan Heath (29/54) Jul 01 2004 I know. Currently, they are...
- Regan Heath (9/61) Jul 01 2004 Small correction, there should be a body in the void foo() function in
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:Agreed.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.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:but what if you wanted to pass a SuperThing into a function that only 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 Heath wrote:Agreed.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.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
Jun 23 2004
Daniel Horn wrote: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.)but what if you wanted to pass a SuperThing into a function that only took a thing and didn't want to use templatesFurthermore: 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.
Jun 23 2004
Norbert Nemec wrote:Daniel Horn wrote:"polymorphism" does not demand for virtual functions by default. 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-EricThat'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.)but what if you wanted to pass a SuperThing into a function that only took a thing and didn't want to use templatesFurthermore: 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.
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:You can't use classes in some cases. With classes you can't model an 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-EricAre 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:classes are on the heap, structs can be on the stack--this is important--esp if you're doing something like a number sort of class or a vectorAre 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
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...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/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
"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:I am a real idiot for not trying to add member variables."Walter" <newshound digitalmars.com> wrote in message news:cc0hlu$9gv$2 digitaldaemon.com...Nope: mixin A!() A is not a templateYou can do the following: struct A { ... } struct B { A a; ... more members ... }Or even (maybe) better: struct A() { } struct B { mixin A!(); // ... more members ... }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...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.On Thu, 1 Jul 2004 14:12:37 +0200, Ivan Senji <ivan.senji public.srce.hr> wrote:I am a real idiot for not trying to add member variables."Walter" <newshound digitalmars.com> wrote in message news:cc0hlu$9gv$2 digitaldaemon.com...Nope: mixin A!() A is not a templateYou can do the following: struct A { ... } struct B { A a; ... more members ... }Or even (maybe) better: struct A() { } struct B { mixin A!(); // ... more members ... }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!-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/Regan -- 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:I finally understand what is troubling you. I read yout previous posts about this but didn't have any time to try it out."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...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.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/Regan -- 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 { #struct B { #void main() { 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: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/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 { #struct B { #void main() { But doesn't help if you have two or more instances of A inside B.
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:that looks like a reasonable solution. 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; };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
"Norbert Nemec" <Norbert.Nemec gmx.de> wrote in message news:cbdq61$2u6v$1 digitaldaemon.com...Regan Heath wrote:Very nice point! I knew there was a point to trawling the posts tonight. Thanks for that. :)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 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...I know. Currently, they are...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.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: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/In article <opr92xf8ba5a2sq9 digitalmars.com>, Regan Heath says...I know. Currently, they are...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.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(); } }
Jul 01 2004