Thread overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 19, 2018 Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
I've long since become bored of this design decision. Is there good reason for it? Why should it be impossible to derive a struct? It can just be a sugar for an `alias this`, but for a case of simple inheritance, `alias this` can be tedious to spot and understand when reading the code. There's also the special case of an empty base-struct. I **constantly** have to do this: struct Derived { static if (Base.tupleof.length == 0) ref inout(Base) base() inout { return *cast(inout(Base)*)&this; } else Base base; alias base this; // the things... } If not that, then the derived class gets an aligned field of nothing populated by one byte of empty base struct. It also wastes the single `alias this` slot that we get in a no-multiple-alias-this world. As far as I can tell, the decision is arbitrary... can we move past this? |
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Thursday, 20 December 2018 at 01:40:02 UTC, Manu wrote:
> I've long since become bored of this design decision. Is there good
> reason for it?
> Why should it be impossible to derive a struct?
>
> It can just be a sugar for an `alias this`,
Yes but another possible semantic for a struct inheritance list would be the structural conformance, i.e duck types, but this will never happen in D since we use constraints for that.
This could even be used as a primitive, simple and clean template system, although restricted to struct/union:
@dummy struct Base { void required(); }
struct Foo : Base { void required(){} }
// we don't expect a Base as param, but something that's conform with Base,
// i.e something that can be statically verified to have `void required();`
void call(@dummy Base base){}
Which in D translates to much, really much verbose and complex code:
struct Base { void required(); }
struct Foo { void required(){} }
void call(B)(B base)
if (__traits(hasMember, B, "required") &&
isSomeFuncion(...) &&
is(ReturnType!(...) == void))
{}
let's say if you want to be 100% exact because nowadays I tend not to use template constraints anymore excepted when they are needed for the correct dispatching to an overload, they are a loss of time otherwise (i know some will hate this alternative point of view... )
|
December 19, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On Wed, Dec 19, 2018 at 6:10 PM Basile B. via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Thursday, 20 December 2018 at 01:40:02 UTC, Manu wrote:
> > I've long since become bored of this design decision. Is there
> > good
> > reason for it?
> > Why should it be impossible to derive a struct?
> >
> > It can just be a sugar for an `alias this`,
>
> Yes but another possible semantic for a struct inheritance list would be the structural conformance, i.e duck types, but this will never happen in D since we use constraints for that.
>
> This could even be used as a primitive, simple and clean template system, although restricted to struct/union:
>
> @dummy struct Base { void required(); }
> struct Foo : Base { void required(){} }
> // we don't expect a Base as param, but something that's
> conform with Base,
> // i.e something that can be statically verified to have
> `void required();`
> void call(@dummy Base base){}
>
> Which in D translates to much, really much verbose and complex code:
>
> struct Base { void required(); }
> struct Foo { void required(){} }
> void call(B)(B base)
> if (__traits(hasMember, B, "required") &&
> isSomeFuncion(...) &&
> is(ReturnType!(...) == void))
> {}
>
> let's say if you want to be 100% exact because nowadays I tend not to use template constraints anymore excepted when they are needed for the correct dispatching to an overload, they are a loss of time otherwise (i know some will hate this alternative point of view... )
I think strong traits are a different thing, otherwise you're
conflating syntax with class inheritance, and nobody will expect that.
I mean, I love strong traits, but make them a proper thing.
Your suggestion is just kinda weird and nobody would anticipate that.
I see no good reason to collide with normal class inheritance syntax
that way.
And that said, I don't think your answer is a comment on *why* it's
not possible today :)
I'd like to know the reason it doesn't just work already.
|
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Thursday, 20 December 2018 at 01:40:02 UTC, Manu wrote:
> I've long since become bored of this design decision. Is there good
> reason for it?
> Why should it be impossible to derive a struct?
>
> It can just be a sugar for an `alias this`, but for a case of simple
> inheritance, `alias this` can be tedious to spot and understand when
> reading the code.
> There's also the special case of an empty base-struct. I
> **constantly** have to do this:
>
> struct Derived
> {
> static if (Base.tupleof.length == 0)
> ref inout(Base) base() inout { return *cast(inout(Base)*)&this; }
> else
> Base base;
> alias base this;
>
> // the things...
> }
>
> If not that, then the derived class gets an aligned field of nothing populated by one byte of empty base struct.
>
> It also wastes the single `alias this` slot that we get in a no-multiple-alias-this world.
>
> As far as I can tell, the decision is arbitrary... can we move past this?
I imagine inheritance comes with things like being able to cast a Derived* to Base*. How do you delete a Base* without knowing it is derived from? Same goes for "virtual" (C++) functions. Virtual destructors and all that vtable stuff you'd normally get aren't used in struct. Instead you need to use the class type with the garbage collector or some hacky work around with scoped. But classes organize their data any way they want, so you need to use a struct as a shell. Not really a because it's not possible, but just like we don't a lot of other stuff, it's a design decision that was made. Gotta poke Walter and see if he's in the "feel's like he doesn't owe us or anyone an explanation" kind of mood or not.
|
December 19, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On 12/19/2018 5:40 PM, Manu wrote: > I've long since become bored of this design decision. Is there good > reason for it? `alias this` can alias to a function, that doesn't work very well with the base class syntax (you also use alias this to a function). > Why should it be impossible to derive a struct? Because polymorphism makes little sense for a value type. > static if (Base.tupleof.length == 0) static if (Base.sizeof == 0) > then the derived class class? struct? Dessert topping? Floor wax? https://www.youtube.com/watch?v=wPO8PqHGWFU (too bad youtube pulled the video part, it's just audio) |
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > > On 12/19/2018 5:40 PM, Manu wrote: > > I've long since become bored of this design decision. Is there good reason for it? > > `alias this` can alias to a function, that doesn't work very well with the base class syntax (you also use alias this to a function). Right, by necessity, because an empty struct member takes padded space in the aggregate. I think C++ gets the empty-base-class mechanic right; it doesn't take space. I'm demonstrating crappy code that appears extremely frequently in lieu. Perhaps you have a better suggestion? > > Why should it be impossible to derive a struct? > > Because polymorphism makes little sense for a value type. It's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot. > > static if (Base.tupleof.length == 0) > > static if (Base.sizeof == 0) Empty struct has sizeof == 1 no? It certainly takes that many bytes as a member, and that 1 byte is naturally padded out to the alignment of the following member. |
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On 12/20/18 3:15 AM, Manu wrote:
> On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d
> <digitalmars-d@puremagic.com> wrote:
>>
>> On 12/19/2018 5:40 PM, Manu wrote:
>> > static if (Base.tupleof.length == 0)
>>
>> static if (Base.sizeof == 0)
>
> Empty struct has sizeof == 1 no? It certainly takes that many bytes as
> a member, and that 1 byte is naturally padded out to the alignment of
> the following member.
Yes, it does take 1 byte. I believe the reasoning was so it could have a unique address and be used in an array.
It's the same in C++ as well, according to the Internet (except for the base class optimization allowance). Note that C++ compilers aren't *required* to implement this.
The difference between inheritance and manual inheritance (i.e. alias this and a member), is that with true inheritance there is no member that has to have it's own distinct address, so it's allowed to take up 0 space
But I would expect your boilerplate could be handled via mixin template pretty easily, then it becomes:
struct Derived
{
mixin DeriveFrom!Base;
}
That it takes up the one alias this slot is a bummer, but really we should implement multiple-alias-this and that problem would be solved.
-Steve
|
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote: > On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote: [...] > > > Why should it be impossible to derive a struct? > > > > Because polymorphism makes little sense for a value type. > > It's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot. [...] Sigh... when is multiple alias this ever going to happen?? T -- Being forced to write comments actually improves code, because it is easier to fix a crock than to explain it. -- G. Steele |
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote: > On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote: >> On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > [...] >> > > Why should it be impossible to derive a struct? >> > >> > Because polymorphism makes little sense for a value type. >> >> It's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot. > [...] > > Sigh... when is multiple alias this ever going to happen?? > > > T When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378 Alex |
December 20, 2018 Re: Why can't we derive struct's? | ||||
---|---|---|---|---|
| ||||
Posted in reply to 12345swordy | On Thu, Dec 20, 2018 at 03:44:34PM +0000, 12345swordy via Digitalmars-d wrote: > On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote: > > On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote: > > > On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > > [...] > > > > > Why should it be impossible to derive a struct? > > > > > > > > Because polymorphism makes little sense for a value type. > > > > > > It's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot. > > [...] > > > > Sigh... when is multiple alias this ever going to happen?? > > > > > > T > > When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378 [...] IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward. T -- "Maybe" is a strange word. When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr. |
Copyright © 1999-2021 by the D Language Foundation