www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Improvement to struct inheritance possible?

reply Danilo <codedan aol.com> writes:
The following code does not work, and I think it may be a bug or 
could need an enhancement:

```d
module app;
import std;

void main() {
     auto x = new Derived(10, 20);
}

struct Base {
     int a;
}

struct Derived
{
     Base base;
     int b;
     alias this = base;

      disable this();

     // `a` is not available for use with constructor parameters.
     //
     this( typeof(a) _a, typeof(b) _b ) {
         //
         // inside the body of the constructor, `a` is available!
         //
         a = _a;
         b = _b;

         writeln( a, ", ", b );
     }
}
```

The use of `typeof(a)` as a constructor parameter gives:
Error: undefined identifier `a`

Instead I have to explicitely use:
```d
this( typeof(this.a) _a, typeof(b) _b )
// or
this( typeof(base.a) _a, typeof(b) _b )
```

I think this may be a bug, because `base` was imported into the 
scope using `alias this = base` and should therefore be available 
as plain `a`.

With class inheritance everything works as expected:
```d
module app;

import std;

class A {
     int x;
}

class B : A {
     int y;
}

class C : B {
     int z;

     this( typeof(x) _x, typeof(y) _y, typeof(z) _z) {
         writeln(
             _x, ", ",
             _y, ", ",
             _z
         );
     }
}

void main() {
     new C(10, 20, 30);
}
```

Could this please get improved a little bit, so "inherited" 
structure members using `alias this` are already available for 
constructor paramaters?

Thanks!
Jan 17
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Thursday, 18 January 2024 at 07:10:49 UTC, Danilo wrote:
 Could this please get improved a little bit, so "inherited" 
 structure members using `alias this` are already available for 
 constructor paramaters?

 Thanks!
Why can't struct be inherited ?C++ has good `struct inheritance`, and it's there. The disadvantage of `C++ inheritance` is that every `subclass` with a template now needs to add its `own name` and ugly `::`, which is becoming increasingly unsightly! This is `very foolish`,
Jan 17
parent reply zjh <fqbqrr 163.com> writes:
On Thursday, 18 January 2024 at 07:28:22 UTC, zjh wrote:

 Why can't struct be inherited ?C++ has good `struct 
 inheritance`, and it's there.
 The disadvantage of `C++ inheritance` is that every `subclass` 
 with a template now needs to add its `own name` and ugly `::`, 
 which is becoming increasingly unsightly! This is `very 
 foolish`,
I look forward to `someone` writing a `compiler plugin` that can compensate for `these shortcomings`. If the compiler allows `various plugins`, it would be very good. Plugins are completely selectable by users, which is equivalent to placing all the `switches` of `'dmd'` in a separate `plugins directory` .
Jan 17
parent reply zjh <fqbqrr 163.com> writes:
On Thursday, 18 January 2024 at 07:32:56 UTC, zjh wrote:
 Plugins are completely selectable by users, which is equivalent 
 to placing all the `switches` of `'dmd'` in a separate `plugins 
 directory` .
Then if you compile someone else's code, of course you need a plugin that someone else uses. However, there should be a `compilation command` that can control the `switch` of the plugin. Moreover, `each library` comes with its own `'compile command'` when released.
Jan 17
parent Danilo <codedan aol.com> writes:
On Thursday, 18 January 2024 at 07:37:10 UTC, zjh wrote:
 Then if you compile someone else's code, of course you need a 
 plugin that someone else uses. However, there should be a 
 `compilation command` that can control the `switch` of the 
 plugin.
 Moreover, `each library` comes with its own `'compile command'` 
 when released.
Can you please start your own thread? Your messages have absolutely nothing to do with my issue/request!
Jan 17
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On Thursday, 18 January 2024 at 07:10:49 UTC, Danilo wrote:
 The following code does not work, and I think it may be a bug 
 or could need an enhancement:

 ```d
 module app;
 import std;

 void main() {
     auto x = new Derived(10, 20);
 }

 struct Base {
     int a;
 }

 struct Derived
 {
     Base base;
     int b;
     alias this = base;

      disable this();

     // `a` is not available for use with constructor parameters.
     //
     this( typeof(a) _a, typeof(b) _b ) {
         //
         // inside the body of the constructor, `a` is available!
         //
         a = _a;
         b = _b;

         writeln( a, ", ", b );
     }
 }
 ```

 The use of `typeof(a)` as a constructor parameter gives:
 Error: undefined identifier `a`

 Instead I have to explicitely use:
 ```d
 this( typeof(this.a) _a, typeof(b) _b )
 // or
 this( typeof(base.a) _a, typeof(b) _b )
 ```
Just FYI, it's kind of a special case that `typeof(this)` works in this context -- there is no "this" at declaration level, it only exists as a parameter to a function. D allows using typeof(this) to mean "the type of an instance" during declarations because it would be awful otherwise. So I think you are playing around the edge of this "special case" and that's why it's not working. I'm actually surprised `typeof(this.a)` works. -Steve
Jan 18
prev sibling next sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 18 January 2024 at 07:10:49 UTC, Danilo wrote:
 The following code does not work, and I think it may be a bug 
 or could need an enhancement:

 ```d
 module app;
 import std;

 void main() {
     auto x = new Derived(10, 20);
 }

 struct Base {
     int a;
 }

 struct Derived
 {
     Base base;
     int b;
     alias this = base;

      disable this();

     // `a` is not available for use with constructor parameters.
     //
     this( typeof(a) _a, typeof(b) _b ) {
         //
         // inside the body of the constructor, `a` is available!
         //
         a = _a;
         b = _b;

         writeln( a, ", ", b );
     }
 }
 ```

 The use of `typeof(a)` as a constructor parameter gives:
 Error: undefined identifier `a`

 Instead I have to explicitely use:
 ```d
 this( typeof(this.a) _a, typeof(b) _b )
 // or
 this( typeof(base.a) _a, typeof(b) _b )
 ```

 I think this may be a bug, because `base` was imported into the 
 scope using `alias this = base` and should therefore be 
 available as plain `a`.

 With class inheritance everything works as expected:
 ```d
 module app;

 import std;

 class A {
     int x;
 }

 class B : A {
     int y;
 }

 class C : B {
     int z;

     this( typeof(x) _x, typeof(y) _y, typeof(z) _z) {
         writeln(
             _x, ", ",
             _y, ", ",
             _z
         );
     }
 }

 void main() {
     new C(10, 20, 30);
 }
 ```

 Could this please get improved a little bit, so "inherited" 
 structure members using `alias this` are already available for 
 constructor paramaters?

 Thanks!
This won't work because `alias this` is not inheritance ini the object oriented, class-based sense. All it does is when you try to access a symbol through a Derived struct (e.g. `Derived d; writeln(d.a);`) that the compiler sees does not exist in Derived, it will rewrite that to `Derived d; writeln(d.base.a);` (and also when you pass a Derived to a method taking a Base, it will automatically be rewritten to pass the Derived struct's Base member to the method instead). You really cannot think of `alias this` as inheritance, because it is not at all the same as the object-oriented concept of inheritance. You'll only run into problems thinking of it that way.
Jan 18
parent Danilo <codedan aol.com> writes:
Thanks for all the replies!

Of course the part "struct inheritance" was nonsense.
The problem has nothing to do with, it's just about
`alias this = xyz` inside classes and structs.



On Thursday, 18 January 2024 at 20:43:30 UTC, Meta wrote:
 All it does is when you try to access a symbol through a 
 Derived struct (e.g. `Derived d; writeln(d.a);`) that the 
 compiler sees does not exist in Derived, it will rewrite that 
 to `Derived d; writeln(d.base.a);`
Perfect! Only thing is missing, that this works everywhere inside classes and structs - including method/constructor parameters. If `a` isn't found, replace it with `base.a`.
Jan 18
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, January 18, 2024 12:10:49 AM MST Danilo via Digitalmars-d wrote:
 The following code does not work, and I think it may be a bug or
 could need an enhancement:
...
 Could this please get improved a little bit, so "inherited"
 structure members using `alias this` are already available for
 constructor paramaters?
The purpose of alias this is to add an implicit conversion to the target. Inside of a struct, it does do some extra work when a symbol isn't recognized and then implicitly converts the this parameter using the alias this to see if that allows the symbol to work, but at its core, alias this really has nothing to do with inheritance. It's just an implicit conversion (and if anything, personally, I think that doing the implicit conversion on the this reference when it's not even explicitly used is just begging for trouble, and I wish that that had not been implemented). As for typeof, having it do implicit conversions seems like it would just be an avenue for bugs. And the situation with classes is completely different, because the members of a base class are actually members of the derived class, not simply brought in via implicit conversion. In general, alias this is a giant footgun - especially in the face of any kind of type introspection - and IMHO, you really should reconsider what you're doing any time that you use it. Unfortunately, it can be necessary for certain classes of things, but extending it to do more is probably the exact opposite of what we should be doing with it if we change it. - Jonathan M Davis
Jan 18
parent reply Danilo <codedan aol.com> writes:
On Thursday, 18 January 2024 at 21:06:22 UTC, Jonathan M Davis 
wrote:
 As for typeof, having it do implicit conversions seems like it 
 would just be an avenue for bugs.
It's not typeof() that does it, it's the compiler that does it in the same way it usually does it. See answer to Meta, above. `alias this = xyz` inside classes and structs: 1. It's useful. And it's allowed to use it like in my first example, for "importing a struct into the main scope". I discovered the small issue when writing a constructor generator, and with this struct it didn't work. 2. It's also about consistency: In my opinion the (virtual) alias created by `alias this = xyz` inside struct/class needs to work everywhere inside the same class/struct. That's why asked if it may be a bug. It's at least an issue if it works only partly. Seen from a programming language design viewpoint, I think it should get enhanced a tiny bit to be more consistent.
Jan 18
parent Danilo <codedan aol.com> writes:
Created an issue, so this can be checked:
- https://issues.dlang.org/show_bug.cgi?id=24345
Jan 18