Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
February 24, 2015 Struct inheritance | ||||
---|---|---|---|---|
| ||||
Hi, Is it possible in D to have inheritance using value types, i.e. structs? Also I don't quite understand how copy ctors work in D. Do I need to implement opAssign(S other) {}, or this(this) {} and what's the difference between these two? Thanks, Amber |
February 24, 2015 Re: Struct inheritance | ||||
---|---|---|---|---|
| ||||
Posted in reply to amber | On Tuesday, 24 February 2015 at 12:05:51 UTC, amber wrote: > Hi, > > Is it possible in D to have inheritance using value types, i.e. structs? No runtime polymorphism, but a kind of sub typing via alias this. struct S { void foo() { writeln("S.foo"); } struct T { S s; alias s this; } T t; t.foo(); // prints S.foo > Also I don't quite understand how copy ctors work in D. Do I need to implement opAssign(S other) {}, or this(this) {} and what's the difference between these two? If available, opAssign will be used in an assignment like x = y; You're custom opAssign can take arbitrary parameter types, so typeof(y) does not have to be typeof(x). postblit is used for copy construction. This could be assignment if no opAssign is provided (not sure about this), but also e.g. passing parameter by value or returning from a function. |
February 24, 2015 Re: Struct inheritance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On Tuesday, 24 February 2015 at 12:16:43 UTC, Tobias Pankrath wrote:
> On Tuesday, 24 February 2015 at 12:05:51 UTC, amber wrote:
>> Hi,
>>
>> Is it possible in D to have inheritance using value types, i.e. structs?
>
> No runtime polymorphism, but a kind of sub typing via alias this.
>
> struct S { void foo() { writeln("S.foo"); }
> struct T { S s; alias s this; }
>
> T t;
> t.foo(); // prints S.foo
>
>
>> Also I don't quite understand how copy ctors work in D. Do I need to implement opAssign(S other) {}, or this(this) {} and what's the difference between these two?
>
> If available, opAssign will be used in an assignment like x = y;
> You're custom opAssign can take arbitrary parameter types, so typeof(y) does not have to be typeof(x).
>
> postblit is used for copy construction. This could be assignment if no opAssign is provided (not sure about this), but also e.g. passing parameter by value or returning from a functions
Thank you Tobias I get it now.
/amber
|
February 24, 2015 Re: Struct inheritance | ||||
---|---|---|---|---|
| ||||
Posted in reply to amber Attachments: | On Tue, 24 Feb 2015 12:05:50 +0000, amber wrote:
> Hi,
>
> Is it possible in D to have inheritance using value types, i.e. structs?
>
> Also I don't quite understand how copy ctors work in D. Do I need to
> implement opAssign(S other) {}, or this(this) {} and what's the
> difference between these two?
there is no "copy constructor" in D. structs are copied by `memcpy()`, and then compiler calls "postblit" aka `this(this)`. it may seem like constructor, but it's not. it's a "fixup", that fixes inconsistencies that are left by `memcpy()`. i.e. when postblit is called, structure is already copied.
and `opAssign` is... well, overloading of "=" operator. it has to manually create a structure copy and manually copy everything you need. and it will never be called by compiler "behind the scenes", like postblit.
|
February 24, 2015 Re: Struct inheritance | ||||
---|---|---|---|---|
| ||||
Posted in reply to amber Attachments: | On Tue, 24 Feb 2015 12:05:50 +0000, amber wrote:
> Hi,
>
> Is it possible in D to have inheritance using value types, i.e. structs?
>
> Also I don't quite understand how copy ctors work in D. Do I need to
> implement opAssign(S other) {}, or this(this) {} and what's the
> difference between these two?
>
> Thanks,
> Amber
p.s. sometimes compiler can use "move" instead of "copy" for structures. in this case it will not call postblit. so if you have some fields in your struct that depends of the structure address... you're in trouble.
|
February 24, 2015 Re: Struct inheritance | ||||
---|---|---|---|---|
| ||||
Posted in reply to ketmar Attachments: | On Tue, 24 Feb 2015 18:19:39 +0000, ketmar wrote:
> On Tue, 24 Feb 2015 12:05:50 +0000, amber wrote:
>
>> Hi,
>>
>> Is it possible in D to have inheritance using value types, i.e. structs?
>>
>> Also I don't quite understand how copy ctors work in D. Do I need to
>> implement opAssign(S other) {}, or this(this) {} and what's the
>> difference between these two?
>
> there is no "copy constructor" in D. structs are copied by `memcpy()`,
> and then compiler calls "postblit" aka `this(this)`. it may seem like
> constructor, but it's not. it's a "fixup", that fixes inconsistencies
> that are left by `memcpy()`. i.e. when postblit is called, structure is
> already copied.
>
> and `opAssign` is... well, overloading of "=" operator. it has to manually create a structure copy and manually copy everything you need. and it will never be called by compiler "behind the scenes", like postblit.
oops. of course, you already has a struct for `opAssign` -- it need `this` after all! ;-) but no automatic copying. it's just a function call, nothing magic here.
|
February 24, 2015 Re: Struct inheritance | ||||
---|---|---|---|---|
| ||||
Posted in reply to ketmar | On Tue, Feb 24, 2015 at 06:22:05PM +0000, ketmar via Digitalmars-d-learn wrote: > On Tue, 24 Feb 2015 12:05:50 +0000, amber wrote: > > > Hi, > > > > Is it possible in D to have inheritance using value types, i.e. structs? > > > > Also I don't quite understand how copy ctors work in D. Do I need to > > implement opAssign(S other) {}, or this(this) {} and what's the > > difference between these two? > > > > Thanks, > > Amber > > p.s. sometimes compiler can use "move" instead of "copy" for structures. in this case it will not call postblit. so if you have some fields in your struct that depends of the structure address... you're in trouble. Yes, basically, D structs are value types, and quite unlike C++ structs. It's a trap to assume C++-like semantics for D structs, because they are actually very different beasts. D structs should not rely on their own address remaining static, because move semantics will cause problems, for example: struct S { int x; int* p; this(int _x) { x = _x; p = &x; // uh-oh } void method() { *p++; // by the time this runs, the struct may // have moved } } S makeStruct() { return S(1); } void main() { auto s = makeStruct(); s.method(); assert(s.x == 2); // KABOOM } The problem is that returning S from makeStruct() makes a bitwise copy of the struct into main's local variable s, which has a different address than the one created in makeStruct(). But s.p still points to the old address of s.x, which is now pointing to invalid memory. For even more fun, do this: void checkItOut(int x, S* s) { assert(x == 10); s.method(); assert(x == 10); // KABOOM } void main() { auto s = makeStruct(); s.method(); checkItOut(10, &s); } Depending on the specifics of your platform, the second assert in checkItOut() may fail, because s.method(), via the stale pointer s.p, will overwrite the stack location where the original s.x was (but which has gone out of scope and is now invalid), and that old location is now being used for one of the parameters of checkItOut(). So calling s.method() will silently corrupt the stack where the parameter is passed. tl;dr, the moral of the story is, don't rely on the address of structs in D staying the same, unless you REALLY know what you're doing. And even then, you're just 1/8 of an inch away from shooting yourself in the foot. T -- All problems are easy in retrospect. |
Copyright © 1999-2021 by the D Language Foundation