www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - `static` function ... cannot access variable in frame of ...

reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
Hey people, I can use some help understanding why the last line 
produces a compile error.

```d
import std.stdio;

struct S
{
     static void foo(alias len)()
     {
         writeln(len);
     }
}

void S_foo(alias len)()
{
     writeln(len);
}

void main()
{

     const five = 5;
     S_foo!five;	// Fine
     S.foo!five; // Error
}
```

The error is
```
onlineapp.d(7): Error: `static` function 
`onlineapp.main.foo!(5).foo` cannot access variable `five` in 
frame of function `D main`
onlineapp.d(19):        `five` declared here
onlineapp.d(21): Error: template instance 
`onlineapp.main.foo!(5)` error instantiating
```

It seems to me this should just work.

Thanks!

--Bastiaan.
Jan 15
next sibling parent Dukc <ajieskola gmail.com> writes:
On Monday, 15 January 2024 at 18:16:44 UTC, Bastiaan Veelo wrote:
 Hey people, I can use some help understanding why the last line 
 produces a compile error.

 ```d
 import std.stdio;

 struct S
 {
     static void foo(alias len)()
     {
         writeln(len);
     }
 }

 void S_foo(alias len)()
 {
     writeln(len);
 }

 void main()
 {

     const five = 5;
     S_foo!five;	// Fine
     S.foo!five; // Error
 }
 ```

 The error is
 ```
 onlineapp.d(7): Error: `static` function 
 `onlineapp.main.foo!(5).foo` cannot access variable `five` in 
 frame of function `D main`
 onlineapp.d(19):        `five` declared here
 onlineapp.d(21): Error: template instance 
 `onlineapp.main.foo!(5)` error instantiating
 ```

 It seems to me this should just work.
It seems that since you write `static` to the member function signature, the compiler thinks the function shouldn't be allowed to have a hidden parameter that is needed to access `const five` from `foo`. At a first glance it seems this should be allowed, since `static` means "no access to the type or function enclosing the member function", which wouldn't appear to say anything about the hidden frame pointer to the `alias` context as opposed to the enclosing struct. But thinking about it, function templates are a shorthand for epnymous templates. I think the code get's rewritten to: ```D struct S { template foo(alias len) { static void foo() { writeln(len); } } } ``` . As you can see, in the rewritten form you actually are accessing the outer scope, which is exactly what `static` is supposed to prevent. On the other hand, if you move the template out of the struct you say this still works, even when it shouldn't according to my theory. I'm of the opinion that something in the compiler needs fixing here, but I'm not quite sure what.
Jan 15
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Mon, Jan 15, 2024 at 06:16:44PM +0000, Bastiaan Veelo via
Digitalmars-d-learn wrote:
 Hey people, I can use some help understanding why the last line
 produces a compile error.
 
 ```d
 import std.stdio;
 
 struct S
 {
     static void foo(alias len)()
[...] The trouble is with the `static` here. A context pointer is necessary in order to have access to the context of main() from the body of this function; but `static` precludes this possibility. T -- It is of the new things that men tire --- of fashions and proposals and improvements and change. It is the old things that startle and intoxicate. It is the old things that are young. -- G.K. Chesterton
Jan 15
parent user1234 <user1234 12.de> writes:
On Monday, 15 January 2024 at 18:34:58 UTC, H. S. Teoh wrote:
 On Mon, Jan 15, 2024 at 06:16:44PM +0000, Bastiaan Veelo via 
 Digitalmars-d-learn wrote:
 Hey people, I can use some help understanding why the last 
 line produces a compile error.
 
 ```d
 import std.stdio;
 
 struct S
 {
     static void foo(alias len)()
[...] The trouble is with the `static` here. A context pointer is necessary in order to have access to the context of main() from the body of this function; but `static` precludes this possibility. T
I dont agree, problem is S_foo that get automagically monomorphized in `main` scope. That's a very classic D problem.
Jan 15
prev sibling parent reply user1234 <user1234 12.de> writes:
On Monday, 15 January 2024 at 18:16:44 UTC, Bastiaan Veelo wrote:
 [...]

 It seems to me this should just work.

 Thanks!

 --Bastiaan.
The two calls are not equivalent. To be equivalent you need to set `S_foo` static too, otherwise `S_Foo` is instanciated in `main` scope, proof: ```d import std.stdio; struct S { static void foo(alias len)() { writeln(len); } } static void S_foo(alias len)() { writeln(len); } void main() { const five = 5; S_foo!five; // Error too now S.foo!five; // Error } ``` so what is passed as alias need to be static too. But to be frank, I agree this is a less ideal situation. There are like 20 bugs reports opened related to that. The way a non-static `S_foo` behaves is under-specified.
Jan 15
parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Monday, 15 January 2024 at 18:43:43 UTC, user1234 wrote:
 The two calls are not equivalent.
 so what is passed as alias need to be static too.
Thanks all. I thought a static member function just isn't able to access the instance of the struct, but as I understand now it is static all the way. What I am looking for is a way to have different structs that have a member function that has the same name in all of them, that is callable without a this pointer, and able to take an alias argument. That is probably asking too much. -- Bastiaan.
Jan 15
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Monday, 15 January 2024 at 22:23:27 UTC, Bastiaan Veelo wrote:
 On Monday, 15 January 2024 at 18:43:43 UTC, user1234 wrote:
 The two calls are not equivalent.
 so what is passed as alias need to be static too.
Thanks all. I thought a static member function just isn't able to access the instance of the struct, but as I understand now it is static all the way. What I am looking for is a way to have different structs that have a member function that has the same name in all of them, that is callable without a this pointer, and able to take an alias argument. That is probably asking too much.
As a workaround, you can alias the outer function in the struct: ```d struct S { alias foo = S_foo; } ``` This might be less than ideal, but at least it works. -Steve
Jan 15
parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Monday, 15 January 2024 at 23:06:00 UTC, Steven Schveighoffer 
wrote:
 As a workaround, you can alias the outer function in the struct:

 ```d
 struct S
 {
     alias foo = S_foo;
 }
 ```

 This might be less than ideal, but at least it works.
It does! And it's good enough for me. Thanks a lot! -- Bastiaan.
Jan 16