www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Struct template instancing inside of class failed

reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
Hi!

I'm not sure if this is an issue or if it was intended this way.

```d
class C(alias a) {
     pragma(msg, "class body: ", a.stringof);
     int internal;
     this(int unused){
         pragma(msg, "class ctor: ", a.stringof);
         internal = a;
     }
}

struct S(alias a) {
     pragma(msg, "struct body:", a.stringof);
     int internal;
     this(int unused){
         pragma(msg, "struct ctor:", a.stringof);
         internal = a;
     }
}

class Test {
     int field = 123;

     C!field c;
     S!field s;

     this(){
         c = new C!field(777); // ok
         assert(c.internal == 123);

         // Error: accessing non-static variable `field` requires 
an instance of `Test`
         s = S!field(777);
     }
}

void main() {
     auto t = new Test;
}

```

Compiler output:
```
class body: field
struct body:field
class ctor: this.this.field
struct ctor:field
app.d(20,20): Error: accessing non-static variable `field` 
requires an instance of `Test`
         internal = a;
                    ^
Error dmd failed with exit code 1.
```

I suspect that class stores template parameter "a" in some hidden 
fields and this behaviour impossible for POD structs?
May 02
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 2 May 2025 at 21:58:50 UTC, Denis Feklushkin wrote:
 Hi!

 I'm not sure if this is an issue or if it was intended this way.

 ```d
 class C(alias a) {
     pragma(msg, "class body: ", a.stringof);
     int internal;
     this(int unused){
         pragma(msg, "class ctor: ", a.stringof);
         internal = a;
     }
 }

 struct S(alias a) {
     pragma(msg, "struct body:", a.stringof);
     int internal;
     this(int unused){
         pragma(msg, "struct ctor:", a.stringof);
         internal = a;
     }
 }

 class Test {
     int field = 123;

     C!field c;
     S!field s;

     this(){
         c = new C!field(777); // ok
         assert(c.internal == 123);

         // Error: accessing non-static variable `field` 
 requires an instance of `Test`
         s = S!field(777);
     }
 }

 void main() {
     auto t = new Test;
 }

 ```

 Compiler output:
 ```
 class body: field
 struct body:field
 class ctor: this.this.field
 struct ctor:field
 app.d(20,20): Error: accessing non-static variable `field` 
 requires an instance of `Test`
         internal = a;
                    ^
 Error dmd failed with exit code 1.
 ```

 I suspect that class stores template parameter "a" in some 
 hidden fields and this behaviour impossible for POD structs?
Theres allot of spooky things here it will compile if you add static to `static int field = 123;` if you want a spooky reference to a variable I suggest my "innate" code avoid this construction logic your playing with ```d template innate(T,T startingvalue=T.init,discrimination...){ T innate=startingvalue; } alias field=innate!(int,123,"field"); ``` if you dont need it run time you should pass ints to templates explictly where possible `struct S(int a) {` etc.
May 02
parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Friday, 2 May 2025 at 22:51:24 UTC, monkyyy wrote:

 I suspect that class stores template parameter "a" in some 
 hidden fields and this behaviour impossible for POD structs?
Theres allot of spooky things here
The main question for me is: why it worked for the class, but not for the struct?
 it will compile if you add static to `static int field = 123;`

 if you want a spooky reference to a variable
(Or function, or delegate)
 I suggest my "innate" code avoid this construction logic your 
 playing with
The whole idea looks something like this: ```d struct S(alias outer_handler) { int internal_field = 1; this(int ctor_arg){ internal_field = ctor_arg; assert(outer_handler + internal_field == 124, "ctor failed"); } void someMethod() { assert(outer_handler + internal_field == 124, "method failed"); } ~this(){ // imitate some destruction process assert(outer_handler + internal_field == 124, "destruction failed"); } } class Test { int field = 123; ref getField() => field; alias S_Inst = S!getField; S_Inst s; this(){ // Error: calling non-static function `getField` requires an instance of type `Test` s = S_Inst(1); } } void main() { auto t = new Test; } ```
May 03
prev sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Fri, May 02, 2025 at 09:58:50PM +0000, Denis Feklushkin via Digitalmars-d
wrote:
 Hi!
 
 I'm not sure if this is an issue or if it was intended this way.
 
 ```d
 class C(alias a) {
     pragma(msg, "class body: ", a.stringof);
     int internal;
     this(int unused){
         pragma(msg, "class ctor: ", a.stringof);
         internal = a;
     }
 }
 
 struct S(alias a) {
     pragma(msg, "struct body:", a.stringof);
     int internal;
     this(int unused){
         pragma(msg, "struct ctor:", a.stringof);
         internal = a;
     }
 }
 
 class Test {
     int field = 123;
 
     C!field c;
     S!field s;
 
     this(){
         c = new C!field(777); // ok
         assert(c.internal == 123);
 
         // Error: accessing non-static variable `field` requires an instance
 of `Test`
         s = S!field(777);
[...] Try `S!(this.field)(777)` maybe? In any case, passing a class-local variable via an alias into a template parameter that tries to access it from inside a function seems rather dangerous and needlessly complex. Why not just pass the value directly, or a reference/pointer to the variable? T -- We are in class, we are supposed to be learning, we have a teacher... Is it too much that I expect him to teach me??? -- RL
May 02
parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Friday, 2 May 2025 at 23:15:24 UTC, H. S. Teoh wrote:
 Try `S!(this.field)(777)` maybe?
I tried it - nothing changes
 In any case, passing a class-local variable via an alias into a 
 template parameter that tries to access it from inside a 
 function seems rather dangerous and needlessly complex.  Why 
 not just pass the value directly, or a reference/pointer to the 
 variable?
This is a reduced example IRL I need to pass some handler into methods and destructors of the structures that are stored in the array in class Test. There is no point in storing it in each instance of the structure - it is the same for all structures in the array. (Yes, of course I can write workarounds for all this, but I wanted to write this code idiomatically)
May 03
parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Saturday, 3 May 2025 at 09:11:47 UTC, Denis Feklushkin wrote:

 IRL I need to pass some handler into methods and destructors of 
 the structures that are stored in the array in class Test.
...Then struct won't be able to know their own offset to access to outer field because array can be of any size /thread
May 03