Re: Generate a pointer to a method of a struct
On Saturday, 15 October 2022 at 01:48:15 UTC, kdevel wrote: Is this consistent? I think all the compilers should error on expressions like `Type.nonStaticMethod` and instead there should be a new __traits dedicated to that, especially because `this` is not a formal parameter.
Re: Generate a pointer to a method of a struct
On Saturday, 15 October 2022 at 01:48:15 UTC, kdevel wrote: $ dmd -unittest -main -run ini ini.d(6): Error: non-constant expression `& bar` ini.d(7): Error: non-constant expression `& bar` ``` Is this consistent? I can attest to consistency using ldc. Each of the following prevent function address re-assignment: immutable string function() f = &S.bar; const string function() f = &S.bar; enum f = &S.bar; In contrast, as would be expected, the following has no such restriction: string function() f = &S.bar; Example: struct S { string bar(){return "Hello";} string foo(){return "Goodbye";} } void main() { string function() f = &S.bar; writeln(f, " ", f()); f = &S.foo; writeln(f, " ", f()); }
Re: Generate a pointer to a method of a struct
On Saturday, 15 October 2022 at 00:31:47 UTC, Iain Buclaw wrote: ``` auto funcptr (alias method) () { return &method; } : fun = funcptr!bar; : ``` Which works but neither dmd nor gdc were able to optimize the additional function call away. pragma(inline, true) auto funcptr (alias method) () Thanks. Just found that ``` template funcptr (alias method) { enum funcptr = &method; } ``` works on both dmd and gdc. This gives rise to questions: Is this code expected to compile and pass its unittest? ``` struct S { void bar () { } } enum ei = &S.bar; immutable i = &S.bar; // line 6 const c = &S.bar; // line 7 unittest { import std.stdio; writeln (ei); writeln (i); writeln (c); } ``` gdc passes while dmd says: ``` $ dmd -unittest -main -run ini ini.d(6): Error: non-constant expression `& bar` ini.d(7): Error: non-constant expression `& bar` ``` Is this consistent?
Re: Generate a pointer to a method of a struct
On Friday, 14 October 2022 at 18:34:58 UTC, kdevel wrote: dmd and gdc optimize the lambda invocations away. Nonetheless the expression looks somewhat too big. To overcome this I tried to generate the function pointer outside of the struct: ``` auto funcptr (alias method) () { return &method; } : fun = funcptr!bar; : ``` Which works but neither dmd nor gdc were able to optimize the additional function call away. pragma(inline, true) auto funcptr (alias method) ()
Generate a pointer to a method of a struct
Given a struct `S` with method `foo`: Any of these expressions ``` &foo &S.foo &.S.foo ``` when they occur inside the struct they represent a delegate and not a function pointer. Is it okay to "extract" and use the function pointer from the delegate in this way: ``` struct S { void function () fp; void foo () { fp = (&bar).funcptr; } void bar () { fp = (&foo).funcptr; } auto fun () // invocation helper { if (! fp) fp = (&foo).funcptr; void delegate () dg; dg.ptr = &this; dg.funcptr = fp; return dg (); } } unittest { S s; s.fun; s.fun; } ``` In [1] Walter suggested to use a "lambda function" which reads (adopted to structs): ``` struct S { : void function (ref S) fp; : void foo () { : fun = function (ref S self) { return self.bar (); }; : } : } ``` dmd and gdc optimize the lambda invocations away. Nonetheless the expression looks somewhat too big. To overcome this I tried to generate the function pointer outside of the struct: ``` auto funcptr (alias method) () { return &method; } : fun = funcptr!bar; : ``` Which works but neither dmd nor gdc were able to optimize the additional function call away. So I replaced the function call with a value: ``` template funcptr (alias method) { immutable funcptr = &method; // (*) } ``` That code compiles under gdc 12.1 but I could not find any dmd version which compiles the code. All say ``` ptrtomethod.d(15): Error: non-constant expression `& bar` ``` Line 15 is the line I marked with `(*)`. Any comments? [1] https://www.digitalmars.com/articles/b68.html Member Function Pointers in D