Thread overview
`static` function ... cannot access variable in frame of ...
Jan 15
Dukc
Jan 15
user1234
Jan 15
user1234
January 15

Hey people, I can use some help understanding why the last line produces a compile error.

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.

January 15

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.

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:

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.

January 15
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
January 15

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:

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.

January 15

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.

January 15
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.
January 15

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:

struct S
{
    alias foo = S_foo;
}

This might be less than ideal, but at least it works.

-Steve

January 16

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:

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.