digitalmars.dip.ideas - Struct inheritance
- Richard (Rikki) Andrew Cattermole (24/24) Sep 19 As an idea this has come up in Razvan's DConf 2024 talk.
- Nick Treleaven (9/33) Sep 19 In the talk, Walter mentioned doing that instead of having `alias
- Richard (Rikki) Andrew Cattermole (9/10) Sep 19 The problem with alias this, is it is not defined as the fallback when
- Richard (Rikki) Andrew Cattermole (6/20) Sep 19 I should mention that this aspect of the proposal while it add new
- Nick Treleaven (11/21) Sep 20 I don't see why you want to overload opDispatch to do subtyping.
- Richard (Rikki) Andrew Cattermole (9/22) Sep 20 Ok so basically implicit conversions with optional target type.
- user1234 (11/35) Sep 20 It's basically the same as `opCast` but called without `cast`. A
- Paul Backus (12/13) Sep 19 Last time this came up on the forums, I did a quick search
- IchorDev (3/7) Sep 20 What about interfaces?
- Richard (Rikki) Andrew Cattermole (4/13) Sep 20 While I do want signatures which would fill this void, the purpose of
- Ogion (26/27) Sep 23 Would be nice to have proper struct inheritance but there are a
- Richard (Rikki) Andrew Cattermole (8/42) Sep 23 It is probably better to completely disable casting up the hierarchy in
- Brad Roberts (4/11) Sep 23 Careful with the term 'proper'. It doesn't add clarity. It does
- Derek Fawcus (40/64) Dec 03 As I recall, the main purpose of 'alias this' is to offer
- Richard (Rikki) Andrew Cattermole (18/63) Dec 03 It is two functionalities yes.
- Derek Fawcus (48/67) Dec 03 Yes, but it is literally equivalent to explicitly embedded one
- Richard (Rikki) Andrew Cattermole (18/102) Dec 03 I'm very wary of this, Walter is pretty against implicit conversions
- Derek Fawcus (22/38) Dec 03 OK.
- Richard (Rikki) Andrew Cattermole (44/88) Dec 03 If you need the control between last field of parent, and first of
- Derek Fawcus (38/38) Dec 04 On Tuesday, 3 December 2024 at 23:18:12 UTC, Richard (Rikki)
- Derek Fawcus (38/40) Dec 04 ```D
- Richard (Rikki) Andrew Cattermole (6/14) Dec 04 Due to no vtables, you cannot override a parent method and have it see
- Derek Fawcus (19/34) Dec 04 So are you saying all three would be like the 'Direct Parent'
- Richard (Rikki) Andrew Cattermole (23/65) Dec 04 Casting a pointer to the parent, would be ``@system``, so what it does
- Derek Fawcus (44/67) Dec 04 Which I guess is reasonable, or even have it as undefined
- Richard (Rikki) Andrew Cattermole (6/33) Dec 04 You need this for things like serialization.
- Derek Fawcus (9/13) Dec 05 I'm not seeing that...
- Richard (Rikki) Andrew Cattermole (6/16) Dec 05 I've written many serialization like libraries in D using UDA's they are...
- Derek Fawcus (11/16) Dec 03 Also as I mentioned elsewhere, I don't like the idea of adding
- Richard (Rikki) Andrew Cattermole (6/10) Dec 03 C++ classes work in -betterC.
- Jonathan M Davis (17/41) Dec 05 After that talk, I discussed struct inheritance briefly with Walter, and...
- Richard (Rikki) Andrew Cattermole (7/59) Dec 05 From my perspective that is mostly an implementation detail.
- Jonathan M Davis (15/39) Dec 05 What isn't an implementation detail is that what Walter proposed would
- Richard (Rikki) Andrew Cattermole (17/62) Dec 05 For the checking of inheritance what I mean is:
- Jonathan M Davis (28/30) Dec 05 Except that that _doesn't_ check for inheritance. It checks for an impli...
- Richard (Rikki) Andrew Cattermole (5/45) Dec 05 Problem is, template parameters also should work, using ``Child :
- Jonathan M Davis (42/46) Dec 05 : tests for implicit conversions. That's all it ever does, and making it...
- Richard (Rikki) Andrew Cattermole (5/5) Dec 05 I suppose we could do > and < comparison of types in template parameters...
- Nick Treleaven (5/12) Dec 06 Deprecating that was attempted:
- Jonathan M Davis (11/28) Dec 06 Walter seems to think that we cannot remove alias this, but he's quite
- Derek Fawcus (19/35) Dec 05 So if I read that correctly, for the latter code example I gave,
- Jonathan M Davis (32/69) Dec 05 The types would be completely independent from one another. It would jus...
- claptrap (5/11) Dec 06 Yay! This will be the new "private is not private" topic. I
- Derek Fawcus (10/22) Dec 06 Then maybe don't refer to it as "struct inheritance", possibly
As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. ```d struct Parent { ... } struct Child : Parent { ... } ``` 2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists. ```d struct Parent { T thing; ref T opDispatch(string:"")() { return this.thing; } } struct Child : Parent { } Child child; T got = child; ```
Sep 19
On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. ```d struct Parent { ... } struct Child : Parent { ... } ```In the talk, Walter mentioned doing that instead of having `alias this`. That would be much less powerful. `alias this` allows hooking conversion to the target type. With `alias this = func; T func();`, you can create the T instance at runtime. It doesn't even have to be the same instance each time. Also T doesn't have to be a struct.2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists. ```d struct Parent { T thing; ref T opDispatch(string:"")() { return this.thing; } } struct Child : Parent { } Child child; T got = child; ```This seems like `alias this` in disguise.
Sep 19
On 20/09/2024 6:57 AM, Nick Treleaven wrote:This seems like |alias this| in disguise.The problem with alias this, is it is not defined as the fallback when nothing else in the hierarchy matches. Here it is better defined, opDispatch should only be chosen after exhausting the hierarchy, both in classes and structs. Eliminating the issues with alias this from the design. We can further restrict it, to only support the parent most type in the hierarchy or only one in the hierarchy. In effect it allows adding a new parent to the top of the hierarchy.
Sep 19
On 20/09/2024 7:04 AM, Richard (Rikki) Andrew Cattermole wrote:On 20/09/2024 6:57 AM, Nick Treleaven wrote:I should mention that this aspect of the proposal while it add new semantics, doesn't have anything special related to the rules of acceptability of opDispatch itself. We'll need to define how opDispatch works in the hierarchy. Otherwise we'll have come right back to the same set of issues as alias this has.This seems like |alias this| in disguise.The problem with alias this, is it is not defined as the fallback when nothing else in the hierarchy matches. Here it is better defined, opDispatch should only be chosen after exhausting the hierarchy, both in classes and structs. Eliminating the issues with alias this from the design. We can further restrict it, to only support the parent most type in the hierarchy or only one in the hierarchy. In effect it allows adding a new parent to the top of the hierarchy.
Sep 19
On Thursday, 19 September 2024 at 19:04:40 UTC, Richard (Rikki) Andrew Cattermole wrote:On 20/09/2024 6:57 AM, Nick Treleaven wrote:I don't see why you want to overload opDispatch to do subtyping. It doesn't seem related to existing opDispatch.This seems like |alias this| in disguise.The problem with alias this, is it is not defined as the fallback when nothing else in the hierarchy matches. Here it is better defined, opDispatch should only be chosen after exhausting the hierarchy, both in classes and structs.Eliminating the issues with alias this from the design. We can further restrict it, to only support the parent most type in the hierarchy or only one in the hierarchy. In effect it allows adding a new parent to the top of the hierarchy.I don't think we need to restrict its capabilities, we just need another syntax for it so we can fix the semantics. If anything I'd like to increase its capabilities. It could be defined as a template method and instantiated with the type of the expected result, and the constraint determines whether the conversion is enabled for that type. In effect, allowing multiple `alias this` with the semantics defined by the aggregate author.
Sep 20
On 21/09/2024 3:23 AM, Nick Treleaven wrote:Eliminating the issues with alias this from the design. We can further restrict it, to only support the parent most type in the hierarchy or only one in the hierarchy. In effect it allows adding a new parent to the top of the hierarchy. I don't think we need to restrict its capabilities, we just need another syntax for it so we can fix the semantics. If anything I'd like to increase its capabilities. It could be defined as a template method and instantiated with the type of the expected result, and the constraint determines whether the conversion is enabled for that type. In effect, allowing multiple |alias this| with the semantics defined by the aggregate author.Ok so basically implicit conversions with optional target type. As long as it is defined as being last resort after looking up through the hierarchy, then that aspect I'm ok with. Child most definition only. You'll need to convince Walter wrt. argument to parameter matching, and he has some strong feelings on this. But as far as the syntax changes are concerned for no target type, I'm ok with that being swapped to, it'll give it somewhere to expand to in the future.
Sep 20
On Friday, 20 September 2024 at 15:23:25 UTC, Nick Treleaven wrote:On Thursday, 19 September 2024 at 19:04:40 UTC, Richard (Rikki) Andrew Cattermole wrote:It's basically the same as `opCast` but called without `cast`. A long time ago this was discussed, (we called that opImpcConvRight). That thing would work but to fix `alias this` problems then the users need to overload much more operators, and that becomes unatural to use, i.e vs `alias this` which works more naturally. Fact is there are plenty of situation where implicit convs are not tried but you want that new op to be tried. Basically that's the exact same situations where currently the compiler has to try if `alias this` is possible.On 20/09/2024 6:57 AM, Nick Treleaven wrote:I don't see why you want to overload opDispatch to do subtyping. It doesn't seem related to existing opDispatch.This seems like |alias this| in disguise.The problem with alias this, is it is not defined as the fallback when nothing else in the hierarchy matches. Here it is better defined, opDispatch should only be chosen after exhausting the hierarchy, both in classes and structs.Eliminating the issues with alias this from the design. We can further restrict it, to only support the parent most type in the hierarchy or only one in the hierarchy. In effect it allows adding a new parent to the top of the hierarchy.I don't think we need to restrict its capabilities, we just need another syntax for it so we can fix the semantics. If anything I'd like to increase its capabilities. It could be defined as a template method and instantiated with the type of the expected result, and the constraint determines whether the conversion is enabled for that type. [...]
Sep 20
On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:As an idea this has come up in Razvan's DConf 2024 talk.Last time this came up on the forums, I did a quick search through Phobos to see how many uses of `alias this` forwarded to a member variable (and could be replaced by struct inheritance) and how many forwarded to a function. My hypothesis before actually checking was that `alias this` to a member variable would be significantly more common than `alias this` to a function. But in reality, they turned out to be equally common. Original post: https://forum.dlang.org/post/nbysytbybvqwgxvdexym forum.dlang.org
Sep 19
On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. 2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists.What about interfaces?
Sep 20
On 20/09/2024 10:14 PM, IchorDev wrote:On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:While I do want signatures which would fill this void, the purpose of this is to get rid of alias this which has some problematic behaviors in symbol lookup.As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. 2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists.What about interfaces?
Sep 20
On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:…Would be nice to have proper struct inheritance but there are a lot of things we have to consider. What about slicing? ```D struct A { int x; } struct B : A { int y; this(int x, int y) { super(x); this.y = y; } } void main() { B b1 = B(1, 2), b2 = B(3, 4); A* p = &b2; *p = b1; writeln(b2); // B(1, 4) } ``` If we want something better than `alias this`, we have to prohibit implicit partial assignment via pointer/reference. When it’s necessary, it would still be possible with `*p = cast(A)b1;`.
Sep 23
On 24/09/2024 2:52 AM, Ogion wrote:On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:It is probably better to completely disable casting up the hierarchy in `` safe`` code. If you need that, use ``opCast``. It is not like with classes, where its guaranteed to have an allocation containing the entire thing, with a vtable. Only concern is when you've got a pointer to a struct, and you cast up. ``opCast!(A*)`` support is likely what we want I think. I'm not sure how we'd do that one. Maybe an attribute?…Would be nice to have proper struct inheritance but there are a lot of things we have to consider. What about slicing? ```D struct A { int x; } struct B : A { int y; this(int x, int y) { super(x); this.y = y; } } void main() { B b1 = B(1, 2), b2 = B(3, 4); A* p = &b2; *p = b1; writeln(b2); // B(1, 4) } ``` If we want something better than `alias this`, we have to prohibit implicit partial assignment via pointer/reference. When it’s necessary, it would still be possible with `*p = cast(A)b1;`.
Sep 23
On 9/23/2024 7:52 AM, Ogion via dip.ideas wrote:On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:Careful with the term 'proper'. It doesn't add clarity. It does implicitly divide everything else into some vague other category of improper, but without actually helping describe any actual particulars.…Would be nice to have proper struct inheritance but there are a lot of things we have to consider.
Sep 23
On Thursday, 19 September 2024 at 15:56:06 UTC, Richard (Rikki) Andrew Cattermole wrote:As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. ```d struct Parent { ... } struct Child : Parent { ... } ``` 2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists. ```d struct Parent { T thing; ref T opDispatch(string:"")() { return this.thing; } } struct Child : Parent { } Child child; T got = child; ```As I recall, the main purpose of 'alias this' is to offer implicit conversion of types. There is also the ability to have a member function called (property-like?), which seems like a somewhat different purpose. When I first saw this inheritance suggestion mentioned (possibly in a recording of one of the DConf sessions), it struck me that something like the 'struct embedding' together with its implicit conversion for member functions on the embedded type may provide a similar mechanism. This is something which is offered by Go/Limbo/Alef/Ken-C, the latter being used as the Plan 9 C compiler. As I recall in the latter it was used for something like: ```C struct Lock { ... }; bool lockit(struct Lock *); struct Foo { ... Lock; ... }; void something(/* ... */) { struct Foo *foo = something_returning_Foo(/* ... */); if (!lockit(foo) { /* some error handling */ } ... } ``` Where the use of lockit() above is then called with '&foo->Lock' as an implicit conversion. Personally, I'd rather have a struct like (POD) thing, even with member functions, which does not allow for the possibility of classful behaviour. If classful behaviour is desired, then somehow adjust classes so that they can be easily used as non-reference types.
Dec 03
On 04/12/2024 8:15 AM, Derek Fawcus wrote:As I recall, the main purpose of 'alias this' is to offer implicit conversion of types. There is also the ability to have a member function called (property-like?), which seems like a somewhat different purpose.It is two functionalities yes. Which is why I've included both the inheritance as well as the reparenting behavior. Otherwise it isn't a complete replacement.When I first saw this inheritance suggestion mentioned (possibly in a recording of one of the DConf sessions), it struck me that something like the 'struct embedding' together with its implicit conversion for member functions on the embedded type may provide a similar mechanism. This is something which is offered by Go/Limbo/Alef/Ken-C, the latter being used as the Plan 9 C compiler. As I recall in the latter it was used for something like: ```C struct Lock { ... }; bool lockit(struct Lock *); struct Foo { ... Lock; ... }; void something(/* ... */) { struct Foo *foo = something_returning_Foo(/* ... */); if (!lockit(foo) { /* some error handling */ } ... } ``` Where the use of lockit() above is then called with '&foo->Lock' as an implicit conversion.As a syntax that would imply multiple of these are possible. Classes in D do not support multiple parent classes, so I don't think adding it for structs is appropriate. If you don't need multiple parents, then the existing syntax works fine. ```d struct Parent { } struct Foo : Parent { } ```Personally, I'd rather have a struct like (POD) thing, even with member functions, which does not allow for the possibility of classful behaviour. If classful behaviour is desired, then somehow adjust classes so that they can be easily used as non-reference types.The class behavior that I do not want here is vtables and casting. Both of these have very good reasons why they would not be appropriate. So there would be differences between them with good reasons why you would want classes over structs still.
Dec 03
On Tuesday, 3 December 2024 at 19:25:08 UTC, Richard (Rikki) Andrew Cattermole wrote:On 04/12/2024 8:15 AM, Derek Fawcus wrote:As I recall, the main purpose of 'alias this' is to offer implicit conversion of types. There is also the ability to have a member function called (property-like?), which seems like a somewhat different purpose.It is two functionalities yes. Which is why I've included both the inheritance as well as the reparenting behavior. Otherwise it isn't a complete replacement.As a syntax that would imply multiple of these are possible.Yes, but it is literally equivalent to explicitly embedded one struct in another, which is already possible. So one could have: ```C struct Foo; struct Bar; struct Wrapper { ... Foo; Bar; ... }; ``` Which is just sugar for this: ```C struct Wrapper { ... struct Foo Foo; struct Bar Bar; ... }; ``` It is just that having the embedded form allows the implicit conversion to happen, as it is a simple unambiguous sugar for accessing the appropriate member.Classes in D do not support multiple parent classes, so I don't think adding it for structs is appropriate.Except D also already allows the explicit form above, but not the sugar for the field reference. This is not inheritance, so there are no issues with embedding multiple structs, no diamond pattern issues, etc. (I believe the Go spec explains all of this.) What this gives is the implicit field conversion which 'alias this' seems to offer some form of, but in a different syntactical form, and allowing multiple such conversions. However it probably won't cover all implicit conversion uses, e.g. 'alias this' to an 'int' member, then assigning the struct to an int var. The scheme I'm suggesting only really covers calling functions with argument conversion.If you don't need multiple parents, then the existing syntax works fine. ```d struct Parent { } struct Foo : Parent { } ```Would your proposal allow: ```d struct Grandad { } struct Dad : Grandad { } struct Child : Dad { } ``` (I'm not sure if the scheme I mention does, I'd have to reread the specs; but I believe it doesn't).
Dec 03
On 04/12/2024 9:19 AM, Derek Fawcus wrote:On Tuesday, 3 December 2024 at 19:25:08 UTC, Richard (Rikki) Andrew Cattermole wrote:I'm very wary of this, Walter is pretty against implicit conversions generally speaking. I'm still trying to get a confirmation about the member-of-operator out of Walter which I have implemented (missing like two features). Given that the utility of this is highly restricted to a subset of compositional needs, and the fact that it relies upon implicit conversions, I do not expect that this would be accepted. However, I am in no way arguing against composition, I agree that it is better than inheritance normally. What this would be replacing, is not where composition is most valuable for. Just in case you are interested, this is the function you would need to modify to implement the matching. https://github.com/dlang/dmd/blob/d8c0e79bfb9ddb0e50603ffafa4c3d5539934f48/compiler/src/dmd/typesem.d#L998On 04/12/2024 8:15 AM, Derek Fawcus wrote:As I recall, the main purpose of 'alias this' is to offer implicit conversion of types. There is also the ability to have a member function called (property-like?), which seems like a somewhat different purpose.It is two functionalities yes. Which is why I've included both the inheritance as well as the reparenting behavior. Otherwise it isn't a complete replacement.As a syntax that would imply multiple of these are possible.Yes, but it is literally equivalent to explicitly embedded one struct in another, which is already possible. So one could have: ```C struct Foo; struct Bar; struct Wrapper { ... Foo; Bar; ... }; ``` Which is just sugar for this: ```C struct Wrapper { ... struct Foo Foo; struct Bar Bar; ... }; ``` It is just that having the embedded form allows the implicit conversion to happen, as it is a simple unambiguous sugar for accessing the appropriate member.I got all that. There is are issues from my perspective surrounding its compositional nature.Classes in D do not support multiple parent classes, so I don't think adding it for structs is appropriate.Except D also already allows the explicit form above, but not the sugar for the field reference. This is not inheritance, so there are no issues with embedding multiple structs, no diamond pattern issues, etc. (I believe the Go spec explains all of this.)What this gives is the implicit field conversion which 'alias this' seems to offer some form of, but in a different syntactical form, and allowing multiple such conversions. However it probably won't cover all implicit conversion uses, e.g. 'alias this' to an 'int' member, then assigning the struct to an int var. The scheme I'm suggesting only really covers calling functions with argument conversion.Right, its a tool for composition. Different set of problems.Yes.If you don't need multiple parents, then the existing syntax works fine. ```d struct Parent { } struct Foo : Parent { } ```Would your proposal allow: ```d struct Grandad { } struct Dad : Grandad { } struct Child : Dad { } ``` (I'm not sure if the scheme I mention does, I'd have to reread the specs; but I believe it doesn't).
Dec 03
On Tuesday, 3 December 2024 at 20:45:32 UTC, Richard (Rikki) Andrew Cattermole wrote:OK. I'd suggest that the member variable version of 'alias this' is also a form of embedding / composition. It allows one to control the exact in-memory layout of the struct so defined. Whereas AFAICT, the inheritance suggestion does not. Issues/Questions with inheritance suggestion: 1. What is the in memory layout? (Presumably the 'parent' elements simply appear first in memory). 2. Inability to control in memory layout. 3. What type is passed to a parent struct member function when called on the child. (Presumably it is the class behaviour of passing the child stuct, with 'isA' relations) (If not, then there are two different behaviours for inheritance - class vs struct) 4. What other parts of the class behaviour will apply? (i.e. will the class implicit mutex lock now be instantiated) (if not, then classes and structs using inheritance will have different threading behaviour)Would your proposal allow: ```d struct Grandad { } struct Dad : Grandad { } struct Child : Dad { } ``` (I'm not sure if the scheme I mention does, I'd have to reread the specs; but I believe it doesn't).Yes.
Dec 03
On 04/12/2024 10:37 AM, Derek Fawcus wrote:On Tuesday, 3 December 2024 at 20:45:32 UTC, Richard (Rikki) Andrew Cattermole wrote:Yes, that would be my thought.OK. I'd suggest that the member variable version of 'alias this' is also a form of embedding / composition. It allows one to control the exact in-memory layout of the struct so defined. Whereas AFAICT, the inheritance suggestion does not. Issues/Questions with inheritance suggestion: 1. What is the in memory layout? (Presumably the 'parent' elements simply appear first in memory).Would your proposal allow: ```d struct Grandad { } struct Dad : Grandad { } struct Child : Dad { } ``` (I'm not sure if the scheme I mention does, I'd have to reread the specs; but I believe it doesn't).Yes.2. Inability to control in memory layout.If you need the control between last field of parent, and first of child, I suspect that this isn't the language feature for you. But if we do need to solve it, we could solve it later on with an attribute. I don't think there is a better way to do it than an attribute, so this can be done later on should we need it, rather than arguing about it now.3. What type is passed to a parent struct member function when called on the child. (Presumably it is the class behaviour of passing the child stuct, with 'isA' relations) (If not, then there are two different behaviours for inheritance - class vs struct)A class will pass a this pointer typed as its class, not a child. ```d import std.stdio; void main() { Child child = new Child; child.method(); Parent parent = child; parent.method; } class Parent { void method() { writeln(typeof(this).stringof); } } class Child : Parent { override void method() { super.method(); writeln(typeof(this).stringof); } } ``` Will output: ``` Parent Child Parent Child ``` Struct inheritance would have the same output.4. What other parts of the class behaviour will apply? (i.e. will the class implicit mutex lock now be instantiated) (if not, then classes and structs using inheritance will have different threading behaviour)There is no vtable, no root type (Object class provides the mutex). Therefore unless its stated, no behavior from classes is coming across to structs. Note: classes do not lock the mutex automatically for you. You must specify the synchronized keyword to make it do it. Unless specified by the user, the temporal properties of each match. Existing structs will not change behavior.
Dec 03
On Tuesday, 3 December 2024 at 23:18:12 UTC, Richard (Rikki) Andrew Cattermole wrote:Sorry, I had Obj-C in mind when I wrote that, and my use of that was over 10 years ago; hence my confusion. So what would your scheme do for the struct equivalent of this, assuming it is even compiles: ```d import std.stdio; void main() { Child child = new Child; child.methB(); writeln(); Parent parent = child; parent.methB; } class Parent { void methB() { writeln("MethB(P) ", typeof(this).stringof); methC(); } void methC() { writeln("MethB(P) ", typeof(this).stringof); } } class Child : Parent { override void methC() { writeln("MethC(C) ", typeof(this).stringof); } } ``` Where the above give this output: ``` $ ldc2 -run class.d MethB(P) Parent MethC(C) Child MethB(P) Parent MethC(C) Child ```
Dec 04
(That was a bit iffy, try this one instead) On Wednesday, 4 December 2024 at 11:10:59 UTC, Derek Fawcus wrote:So what would your scheme do for the struct equivalent of this, assuming it is even compiles:```D import std.stdio; void main() { Parent parent = new Parent; parent.methB("Direct"); writeln(); Child child = new Child; child.methB("Inherit"); writeln(); parent = child; parent.methB("Assign"); } class Parent { void methB(string s) { writeln("MethB(P) ", s, " ", typeof(this).stringof); methC(s); } void methC(string s) { writeln("MethC(P) ", s, " ", typeof(this).stringof); } } class Child : Parent { override void methC(string s) { writeln("MethC(C) ", s, " ", typeof(this).stringof); } } ``` For which I get: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit Parent MethC(C) Inherit Child MethB(P) Assign Parent MethC(C) Assign Child ```
Dec 04
On 05/12/2024 12:38 AM, Derek Fawcus wrote:For which I get: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit ParentDue to no vtables, you cannot override a parent method and have it see the override. MethC(C) Inherit Parent```The last example, assignment, this requires vtables and casting up. Which structs cannot do.
Dec 04
On Wednesday, 4 December 2024 at 11:51:57 UTC, Richard (Rikki) Andrew Cattermole wrote:On 05/12/2024 12:38 AM, Derek Fawcus wrote:So are you saying all three would be like the 'Direct Parent' case? Presumably by making the Assign case cheat (manually forcibly casting a pointer of the child to a pointer of the parent), it would also yield the same result. i.e.: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit Parent MethC(P) Inherit Parent MethB(P) Assign Parent MethC(P) Assign Parent ``` Or for the child method override, would you simply yield a compile failure - as it can never work, and has no backward compatibility issue?For which I get: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit ParentDue to no vtables, you cannot override a parent method and have it see the override. MethC(C) Inherit Parent```The last example, assignment, this requires vtables and casting up. Which structs cannot do.
Dec 04
On 05/12/2024 1:03 AM, Derek Fawcus wrote:On Wednesday, 4 December 2024 at 11:51:57 UTC, Richard (Rikki) Andrew Cattermole wrote:Casting a pointer to the parent, would be `` system``, so what it does is very much "good luck with that".On 05/12/2024 12:38 AM, Derek Fawcus wrote:So are you saying all three would be like the 'Direct Parent' case? Presumably by making the Assign case cheat (manually forcibly casting a pointer of the child to a pointer of the parent), it would also yield the same result.For which I get: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit ParentDue to no vtables, you cannot override a parent method and have it see the override. MethC(C) Inherit Parent```The last example, assignment, this requires vtables and casting up. Which structs cannot do.i.e.: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit Parent MethC(P) Inherit Parent MethB(P) Assign Parent MethC(P) Assign Parent ``` Or for the child method override, would you simply yield a compile failure - as it can never work, and has no backward compatibility issue?In a situation such as: ```d struct Parent { void method1() { method2(); } void method2() { } } struct Child : Parent { override void method2() { } } ``` My general view is that you have to be a little bit smart about it. There may be reasons you would want something like this, but there is also reasons it might not be desired. I want a way to reinterpret parent methods as if it was in the child if not overriden. At which point ``method1`` would see the child ``method2`` rather than the one in the parent.
Dec 04
On Wednesday, 4 December 2024 at 12:43:49 UTC, Richard (Rikki) Andrew Cattermole wrote:Casting a pointer to the parent, would be `` system``, so what it does is very much "good luck with that".Which I guess is reasonable, or even have it as undefined behaviour.In a situation such as: ```d struct Parent { void method1() { method2(); } void method2() { } } struct Child : Parent { override void method2() { } } ``` My general view is that you have to be a little bit smart about it. There may be reasons you would want something like this, but there is also reasons it might not be desired.My thinking, and reason for asking, is that two different authors may be involved. One would not wish the fact that someone had Child inherit from Parent cause the behaviour of Parent to change, that way lies madness. Given these are structs, not classes; and the author of Parent would have no expectation of anything other than its own method being called.I want a way to reinterpret parent methods as if it was in the child if not overriden. At which point ``method1`` would see the child ``method2`` rather than the one in the parent.Isn't that simply what I described as 'madness' above? One would seem to be exposing the Parent method to an unexpected code change, as one can not know what other Parent private state may be updated based upon the call to method2 being changed. That strikes me as causing non-determinism. I could see a use for this sort of thing: ```d struct Parent { void method1() { method3(); } void method2() { } void method3() { } } struct Child : Parent { override void method2() { method1(); } override void method3() { } } ``` Where the Child call from method2() to method1() invokes the Parent version, yet the Parent call from method1() to method3() will only ever invoke the Parent version. That means the behaviour of Parent stays consistent. To allow method3() to be redirected, is classful behaviour, and should not be forced upon an existing library of structs just because of what the child did. If one wants classes, use classes - as that sort of result is expected to be possible there.
Dec 04
On 05/12/2024 6:22 AM, Derek Fawcus wrote:I want a way to reinterpret parent methods as if it was in the child if not overriden. At which point |method1| would see the child | method2| rather than the one in the parent. Isn't that simply what I described as 'madness' above? One would seem to be exposing the Parent method to an unexpected code change, as one can not know what other Parent private state may be updated based upon the call to method2 being changed. That strikes me as causing non-determinism. I could see a use for this sort of thing: |struct Parent { void method1() { method3(); } void method2() { } void method3() { } } struct Child : Parent { override void method2() { method1(); } override void method3() { } } | Where the Child call from method2() to method1() invokes the Parent version, yet the Parent call from method1() to method3() will only ever invoke the Parent version. That means the behaviour of Parent stays consistent. To allow method3() to be redirected, is classful behaviour, and should not be forced upon an existing library of structs just because of what the child did. If one wants classes, use classes - as that sort of result is expected to be possible there.You need this for things like serialization. Since we don't have runtime reflection it has to be done at CT, and if you have to do anything to offer it as a user, its just a NOPE compared to other languages. Its needed for both structs and classes.
Dec 04
On Wednesday, 4 December 2024 at 21:49:02 UTC, Richard (Rikki) Andrew Cattermole wrote:You need this for things like serialization.I'm not seeing that...Since we don't have runtime reflection it has to be done at CT, and if you have to do anything to offer it as a user, its just a NOPE compared to other languages.Given that Go and Java use a form of UDA for assisting in serialisation, I don't see that the equivalent for D would be unacceptable. One either writes complex schemes for per structure callbacks, or one uses simple annotation with UDA. I know which I prefer, since it involves writing less code.
Dec 05
On 06/12/2024 8:12 AM, Derek Fawcus wrote:Since we don't have runtime reflection it has to be done at CT, and if you have to do anything to offer it as a user, its just a NOPE compared to other languages. Given that Go and Java use a form of UDA for assisting in serialisation, I don't see that the equivalent for D would be unacceptable. One either writes complex schemes for per structure callbacks, or one uses simple annotation with UDA. I know which I prefer, since it involves writing less code.I've written many serialization like libraries in D using UDA's they are amazing. But you still need access to the child most type to do the introspection upon, and that in the case of classes means the user writing code for every child class.
Dec 05
On Tuesday, 3 December 2024 at 19:15:39 UTC, Derek Fawcus wrote:Personally, I'd rather have a struct like (POD) thing, even with member functions, which does not allow for the possibility of classful behaviour. If classful behaviour is desired, then somehow adjust classes so that they can be easily used as non-reference types.Also as I mentioned elsewhere, I don't like the idea of adding such to the betterC subset. If one wants classful behaviour in betterC, then I'd suggest somehow making classes work in betterC, and leaving structs without and possibility of classful stuff. That keeps more closely to the spirit of C, and without any of the Simula-67 like C-with-Classes stuff. Even then, I'd rather not have any form of classful behaviour (i.e. struct inheritance) in betterC, but that is obviously just my personal preference.
Dec 03
On 04/12/2024 8:30 AM, Derek Fawcus wrote:If one wants classful behaviour in betterC, then I'd suggest somehow making classes work in betterC, and leaving structs without and possibility of classful stuff. That keeps more closely to the spirit of C, and without any of the Simula-67 like C-with-Classes stuff.C++ classes work in -betterC. Its not too difficult to implement down casting either. https://github.com/Project-Sidero/basic_memory/blob/main/source/sidero/base/allocators/classes.d I.e. https://github.com/Project-Sidero/fileformats/blob/master/source/sidero/fileformats/errors.d
Dec 03
On Thursday, September 19, 2024 9:56:06 AM MST Richard Andrew Cattermole (Rikki) via dip.ideas wrote:As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. ```d struct Parent { ... } struct Child : Parent { ... } ``` 2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists. ```d struct Parent { T thing; ref T opDispatch(string:"")() { return this.thing; } } struct Child : Parent { } Child child; T got = child; ```After that talk, I discussed struct inheritance briefly with Walter, and his idea was that if we did it, there would be _no_ conversions of any kind that came from it. It would purely be a way to have a struct inherit all of the fields and member functions from the "parent" struct and as such would essentially be the compiler copying and pasting that code into the struct doing the inheriting. So, it would provide a way to inherit / copy the implementation, but the types would be completely divorced from one another in terms of how they were used. Personally, I think that that's the right approach, since it's the issues around implicit conversions that are the core problem with alias this, and it avoids all issues with regards to slicing objects (which is the primary reason why classes in D are on the heap instead of on the stack like they can be in C++). - Jonathan M Davis
Dec 05
On 06/12/2024 11:41 AM, Jonathan M Davis wrote:On Thursday, September 19, 2024 9:56:06 AM MST Richard Andrew Cattermole (Rikki) via dip.ideas wrote:From my perspective that is mostly an implementation detail. The reason it is not fully an implementation detail is due to methods effectively having what I've been calling `` reinterpretAsChild`` turned on. We can still make overrides, and is expression to check if it inherits from the parent type to work. I'm ok with this approach. It simplifies a bunch of problems down.As an idea this has come up in Razvan's DConf 2024 talk. 1. Support inheritance on struct, for other structs. ```d struct Parent { ... } struct Child : Parent { ... } ``` 2. ``opDispatch`` function, may work in place of ``alias this`` when no parent exists. ```d struct Parent { T thing; ref T opDispatch(string:"")() { return this.thing; } } struct Child : Parent { } Child child; T got = child; ```After that talk, I discussed struct inheritance briefly with Walter, and his idea was that if we did it, there would be _no_ conversions of any kind that came from it. It would purely be a way to have a struct inherit all of the fields and member functions from the "parent" struct and as such would essentially be the compiler copying and pasting that code into the struct doing the inheriting. So, it would provide a way to inherit / copy the implementation, but the types would be completely divorced from one another in terms of how they were used. Personally, I think that that's the right approach, since it's the issues around implicit conversions that are the core problem with alias this, and it avoids all issues with regards to slicing objects (which is the primary reason why classes in D are on the heap instead of on the stack like they can be in C++). - Jonathan M Davis
Dec 05
On Thursday, December 5, 2024 4:10:46 PM MST Richard (Rikki) Andrew Cattermole via dip.ideas wrote:What isn't an implementation detail is that what Walter proposed would involve _zero_ conversions. So, there would be no casting to a parent from a child or vice versa unless you explicitly implemented casts for that. With what Walter was looking to do with struct inheritance, it would not be creating at type hierarchy at all. It would purely be a way to copy the implementation. So, there would nothing like reinterpretAsChild. The types would effectively be unrelated to one another as far as the type system was concerned. And if we _did_ have some sort of is expression to test whether one struct inherited from another, it couldn't be the same one that's used for classes, because there is no conversion (though honestly, the fact that we test for inheritance via implicit conversion with classes is broken given the fact that alias this exists). - Jonathan M DavisAfter that talk, I discussed struct inheritance briefly with Walter, and his idea was that if we did it, there would be _no_ conversions of any kind that came from it. It would purely be a way to have a struct inherit all of the fields and member functions from the "parent" struct and as such would essentially be the compiler copying and pasting that code into the struct doing the inheriting. So, it would provide a way to inherit / copy the implementation, but the types would be completely divorced from one another in terms of how they were used. Personally, I think that that's the right approach, since it's the issues around implicit conversions that are the core problem with alias this, and it avoids all issues with regards to slicing objects (which is the primary reason why classes in D are on the heap instead of on the stack like they can be in C++). - Jonathan M DavisFrom my perspective that is mostly an implementation detail. The reason it is not fully an implementation detail is due to methods effectively having what I've been calling `` reinterpretAsChild`` turned on. We can still make overrides, and is expression to check if it inherits from the parent type to work. I'm ok with this approach. It simplifies a bunch of problems down.
Dec 05
On 06/12/2024 1:14 PM, Jonathan M Davis wrote:On Thursday, December 5, 2024 4:10:46 PM MST Richard (Rikki) Andrew Cattermole via dip.ideas wrote:For the checking of inheritance what I mean is: ``is(Child : Parent)`` The same as a class has. Something the compiler certainly has the ability to offer. For casting, you could only do it via pointers in `` system`` code, you can do this today. No way would it be appropriate to add a new form of casting. Since there is no vtable or guarantee of heap allocation. As for `` reinterpretAsChild`` it would effectively be turned on and couldn't be opt-out, and would be a better way of describing this behavior as it would exist for classes. Rather than introducing some new unique to struct behavior. This needs a DIP written to make this stuff clear. So that'll be a next months job. Because I understand what you're saying and what Walter is concerned with based upon your statement. Its just that the spec and the implementation are going to have different concerns and they need to be aligned for both the end user and for it to be implementable.What isn't an implementation detail is that what Walter proposed would involve _zero_ conversions. So, there would be no casting to a parent from a child or vice versa unless you explicitly implemented casts for that. With what Walter was looking to do with struct inheritance, it would not be creating at type hierarchy at all. It would purely be a way to copy the implementation. So, there would nothing like reinterpretAsChild. The types would effectively be unrelated to one another as far as the type system was concerned. And if we _did_ have some sort of is expression to test whether one struct inherited from another, it couldn't be the same one that's used for classes, because there is no conversion (though honestly, the fact that we test for inheritance via implicit conversion with classes is broken given the fact that alias this exists). - Jonathan M DavisAfter that talk, I discussed struct inheritance briefly with Walter, and his idea was that if we did it, there would be _no_ conversions of any kind that came from it. It would purely be a way to have a struct inherit all of the fields and member functions from the "parent" struct and as such would essentially be the compiler copying and pasting that code into the struct doing the inheriting. So, it would provide a way to inherit / copy the implementation, but the types would be completely divorced from one another in terms of how they were used. Personally, I think that that's the right approach, since it's the issues around implicit conversions that are the core problem with alias this, and it avoids all issues with regards to slicing objects (which is the primary reason why classes in D are on the heap instead of on the stack like they can be in C++). - Jonathan M DavisFrom my perspective that is mostly an implementation detail. The reason it is not fully an implementation detail is due to methods effectively having what I've been calling `` reinterpretAsChild`` turned on. We can still make overrides, and is expression to check if it inherits from the parent type to work. I'm ok with this approach. It simplifies a bunch of problems down.
Dec 05
On Thursday, December 5, 2024 5:35:38 PM MST Richard (Rikki) Andrew Cattermole via dip.ideas wrote:For the checking of inheritance what I mean is: ``is(Child : Parent)``Except that that _doesn't_ check for inheritance. It checks for an implicit conversion. It's just used for checking for inheritance based on the fact that a reference to a child class can implicitly convert to a reference of its parent class. It's already fundamentally broken in the sense that alias this can make it incorrect if you're testing for inheritance, e.g. ``` void main() { auto foo = new Foo; A a = foo; static assert(is(Foo : A)); } class A {} class Foo { A a; alias this = a; } ``` Really, we need something in __traits to test for inheritance and to stop using is expressions for it. Either way, it's fundamentally wrong to have is(Child : Parent) tell you that a struct named Child inherits from a struct named Parent, because they wouldn't have an implicit conversion, and : is testing specifically for an implicit conversion. - Jonathan M Davis
Dec 05
On 06/12/2024 2:04 PM, Jonathan M Davis wrote:On Thursday, December 5, 2024 5:35:38 PM MST Richard (Rikki) Andrew Cattermole via dip.ideas wrote:Problem is, template parameters also should work, using ``Child : Parent`` syntax. Otherwise the usability on this is going to be absolutely atrocious in meta-programming.For the checking of inheritance what I mean is: ``is(Child : Parent)``Except that that _doesn't_ check for inheritance. It checks for an implicit conversion. It's just used for checking for inheritance based on the fact that a reference to a child class can implicitly convert to a reference of its parent class. It's already fundamentally broken in the sense that alias this can make it incorrect if you're testing for inheritance, e.g. ``` void main() { auto foo = new Foo; A a = foo; static assert(is(Foo : A)); } class A {} class Foo { A a; alias this = a; } ``` Really, we need something in __traits to test for inheritance and to stop using is expressions for it. Either way, it's fundamentally wrong to have is(Child : Parent) tell you that a struct named Child inherits from a struct named Parent, because they wouldn't have an implicit conversion, and : is testing specifically for an implicit conversion. - Jonathan M Davis
Dec 05
On Thursday, December 5, 2024 6:13:04 PM MST Richard (Rikki) Andrew Cattermole via dip.ideas wrote:Problem is, template parameters also should work, using ``Child : Parent`` syntax. Otherwise the usability on this is going to be absolutely atrocious in meta-programming.: tests for implicit conversions. That's all it ever does, and making it do anything else will introduce inconsistencies into the language. For instance, since struct inheritance would _not_ involve an implicit conversion, how would you test for an implicit conversion if is(T : U) were true because T inherited from U? After all, since we're unfortunately not actually going to get rid of alias this, it would be quite possible to have T inherit from U an then have an alias this which makes it implicitly convert to U. Code that wants to test for struct inheritance can do so with a template constraint and a __traits trait just like plenty of other code does. There's nothing special about inheritance, let alone struct inheritance that makes it any different. Also, honestly, I don't think that testing for struct inheritance with metaprogramming is even likely to be a valid use case outside of niche situations. There is no conversion unless the programmer explicitly adds one, so a "child" type can't be treated as if it were the same as its "parent" type, and if templated code wants to use the API of the parent struct so that it works with any struct type that's derived from it, it's arguably better to test its API and not anything inheritance-related, because it's the API that actually matters for using it, not whether that API was inherited from a particular struct. And if it's the API that's tested, then it can work with any type with that API regardless of whether it's derived from a particular struct. Really, if struct inheritance does not involve implicit conversion, then I don't think that there's much reason to even care that that relationship exists. They're just two types which happen to have some of the same members, and if they need to be used by the same code, it's going to need to be templated just like happens with any two unrelated types which share enough of the same API to be duck typed together. And there's no need to take the inheritance into account at all with that code. It's simply the API that matters, not where the implementation happens to have come from. Either way, given that : is specifically for testing implicit conversions, it's really not appropriate to conflate it with inheritance when implict conversions aren't involved. And even for class inheritance, which has the implicit conversion, it's arguably a mistake to use it to test for inheritance, because it's testing for an implicit conversion, not inheritance, and the implicit conversion can be there for other reasons. So, in general, we should be moving away from using is(T : U) to test for inheritance of any kind, not making struct inheritance use it too. - Jonathan M Davis
Dec 05
I suppose we could do > and < comparison of types in template parameters and is expressions. Which could be hierarchy based instead of implicit conversions. I would need to double check it, but ok I can ditch the : in favor of > here.
Dec 05
On Friday, 6 December 2024 at 01:04:37 UTC, Jonathan M Davis wrote:class A {} class Foo { A a; alias this = a; } ```Deprecating that was attempted: https://dlang.org/changelog/2.103.0.html#dmd.deprecate-alias-this-for-classes Is deprecation/removal planned for a future edition?
Dec 06
On Friday, December 6, 2024 4:42:14 AM MST Nick Treleaven via dip.ideas wrote:On Friday, 6 December 2024 at 01:04:37 UTC, Jonathan M Davis wrote:Walter seems to think that we cannot remove alias this, but he's quite averse to removing anything at this point, because he's paranoid about breaking code and just generally seems to be against deprecating anything. I don't know what he'll be willing to consider when it comes to alias this and editions. At present, I don't think that much of anything is actually planned for editions in terms of what we're going to change. Ideas have been bandied around, and Walter should be more amenable to breaking changes with editions (since that's at least partially the idea behind them), but we'll have to see what actually happens. - Jonathan M Davisclass A {} class Foo { A a; alias this = a; } ```Deprecating that was attempted: https://dlang.org/changelog/2.103.0.html#dmd.deprecate-alias-this-for-classe s Is deprecation/removal planned for a future edition?
Dec 06
On Thursday, 5 December 2024 at 22:41:25 UTC, Jonathan M Davis wrote:After that talk, I discussed struct inheritance briefly with Walter, and his idea was that if we did it, there would be _no_ conversions of any kind that came from it. It would purely be a way to have a struct inherit all of the fields and member functions from the "parent" struct and as such would essentially be the compiler copying and pasting that code into the struct doing the inheriting. So, it would provide a way to inherit / copy the implementation, but the types would be completely divorced from one another in terms of how they were used. Personally, I think that that's the right approach, since it's the issues around implicit conversions that are the core problem with alias this, and it avoids all issues with regards to slicing objects (which is the primary reason why classes in D are on the heap instead of on the stack like they can be in C++).So if I read that correctly, for the latter code example I gave, assuming use of structs rather and classes, and adjusted... The 'Assign' case would be a compile error, and once removed it would yield: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit Child MethC(C) Inherit Child ``` Is that correct? Also is it the case that method overrides would dominate over any 'pasted' method from the parent - i.e. the MethC case? Or would those be forbidden as a name conflict? Presumably one could not have data fields with the same name in the Parent and Child, or would there be a rule for resolving that conflict?
Dec 05
On Thursday, December 5, 2024 4:36:17 PM MST Derek Fawcus via dip.ideas wrote:On Thursday, 5 December 2024 at 22:41:25 UTC, Jonathan M Davis wrote:The types would be completely independent from one another. It would just be a way to copy the implementation from one to the other. So, no conversions or assignments would ever take place without some explicit code handling it, just like normally occurs with any two types which have nothing to do with one another. It's purely an inheritance of implementation and would not create a hierarchy like you get with classes. So, it would therefore avoid all of the various issues that you get with class inheritance and objects on the stack in C++ - but it also wouldn't get any form of polymorphism. It would just be a way to share code.After that talk, I discussed struct inheritance briefly with Walter, and his idea was that if we did it, there would be _no_ conversions of any kind that came from it. It would purely be a way to have a struct inherit all of the fields and member functions from the "parent" struct and as such would essentially be the compiler copying and pasting that code into the struct doing the inheriting. So, it would provide a way to inherit / copy the implementation, but the types would be completely divorced from one another in terms of how they were used. Personally, I think that that's the right approach, since it's the issues around implicit conversions that are the core problem with alias this, and it avoids all issues with regards to slicing objects (which is the primary reason why classes in D are on the heap instead of on the stack like they can be in C++).So if I read that correctly, for the latter code example I gave, assuming use of structs rather and classes, and adjusted... The 'Assign' case would be a compile error, and once removed it would yield: ``` MethB(P) Direct Parent MethC(P) Direct Parent MethB(P) Inherit Child MethC(C) Inherit Child ``` Is that correct?Also is it the case that method overrides would dominate over any 'pasted' method from the parent - i.e. the MethC case? Or would those be forbidden as a name conflict?IIRC, from what Walter said, if the child implemented the same member function as the parent, the child's would take precedence, and the parent's would basically not exist in the child.Presumably one could not have data fields with the same name in the Parent and Child, or would there be a rule for resolving that conflict?I didn't discuss that particular issue with Walter, so I don't know what his stance would be, but the most obvious thing would presumably be to just make it illegal. Particularly when you're dealing with private members, it's not like it would be a big deal to just name the member variable something else to avoid the conflict. We had a fairly quick discussion on some of the obvious issues that I thought of off the top of my head (e.g. conversions and object slicing), but it's not like we sat down and hashed it all out in detail. So, if/when Walter decides to implement it, he'll have to sort that out with a DIP (or he'll have to approve someone else's DIP where they provide all of those details). But the discussion _was_ enough to make it clear that Walter's intention was to use struct inheritance purely as a way to inherit the implementation and _not_ as a way to provide any sort of implicit conversions or a way to use one type as another (though templated code could use duck typing like it normally does to work with types that have the appropriate API, so you could have the same code work with multiple struct types that inherited from the same parent, since they'd all have the API from the parent). - Jonathan M Davis
Dec 05
On Friday, 6 December 2024 at 00:06:12 UTC, Jonathan M Davis wrote:On Thursday, December 5, 2024 4:36:17 PM MST Derek Fawcus viaYay! This will be the new "private is not private" topic. I expect a deluge of ****posting complaining that struct inheritance is not inheritance.Is that correct?The types would be completely independent from one another. It would just be a way to copy the implementation from one to the other.
Dec 06
On Friday, 6 December 2024 at 12:21:02 UTC, claptrap wrote:On Friday, 6 December 2024 at 00:06:12 UTC, Jonathan M Davis wrote:Then maybe don't refer to it as "struct inheritance", possibly use something like "struct inclusion", or "struct addition". Plus maybe a different syntax, e.g.: ```d struct A { } struct B += A { } ```On Thursday, December 5, 2024 4:36:17 PM MST Derek Fawcus viaYay! This will be the new "private is not private" topic. I expect a deluge of ****posting complaining that struct inheritance is not inheritance.Is that correct?The types would be completely independent from one another. It would just be a way to copy the implementation from one to the other.
Dec 06