digitalmars.D.learn - Generate a pointer to a method of a struct
- kdevel (79/79) Oct 14 2022 Given a struct `S` with method `foo`: Any of these expressions
- Iain Buclaw (3/17) Oct 14 2022 pragma(inline, true)
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
Oct 14 2022
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) ()
Oct 14 2022
On Saturday, 15 October 2022 at 00:31:47 UTC, Iain Buclaw wrote: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?``` 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) ()
Oct 14 2022
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()); }
Oct 15 2022
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.
Oct 15 2022