www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Member function passed through template alias only requiring `this` in

reply Emma <VuLXn6DBW PPtUm7TvV6nsw.com> writes:
Hello,

I’ve got this piece of code:

---
import std.stdio;

void test(alias fn1, alias fn2)()
{
     fn1();
     fn2();
}

struct Foo
{
     void foo()
     {
         test!(bar, baz);
     }

     void bar()
     {}

     void baz()
     {}
}
---

If I try to compile it, dmd complains, which I guess makes sense:

---
Error: need this for bar of type void()
Error: need this for baz of type void()
---

However, if I change line 13 from `test!(bar, baz);` to `test!(() 
=> bar, baz);`, it compiles and executes fine, calling both the 
`bar` and `baz` member functions.

Why is this? Shouldn’t it complain about `baz` needing `this`? 
Does the lambda in the first template argument somehow “pull in” 
the `this` reference for `baz`, too?

Thanks!
Jul 19 2018
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/19/2018 08:12 AM, Emma wrote:

 void test(alias fn1, alias fn2)()
 {
      fn1();
      fn2();
 }

 struct Foo
 {
      void foo()
      {
          test!(bar, baz);
      }

      void bar()
      {}

      void baz()
      {}
 }
 ---

 If I try to compile it, dmd complains, which I guess makes sense:

 ---
 Error: need this for bar of type void()
 Error: need this for baz of type void()
 ---

 However, if I change line 13 from `test!(bar, baz);` to `test!(() =>
 bar, baz);`, it compiles and executes fine, calling both the `bar` and
 `baz` member functions.

 Why is this? Shouldn’t it complain about `baz` needing `this`? Does the
 lambda in the first template argument somehow “pull in” the `this`
 reference for `baz`, too?

 Thanks!
I think it's a compiler bug. The second template argument should be a lambda as well. When I added the following lines to test() pragma(msg, typeof(fn1)); pragma(msg, typeof(fn2)); the output is different: void delegate() system void() I think it's a bug probably related to multiple local lambdas. We had similar issues in the past. Although it works as is, I recommend you make the second one a lambda as well. Others, please confirm that it's a bug and let's create a bug report. Ali
Jul 19 2018
parent Timoses <timosesu gmail.com> writes:
On Thursday, 19 July 2018 at 22:16:22 UTC, Ali Çehreli wrote:
 On 07/19/2018 08:12 AM, Emma wrote:
 [...]
 If I try to compile it, dmd complains, which I guess makes
sense:
 ---
 Error: need this for bar of type void()
 Error: need this for baz of type void()
 ---

 [...]
I think it's a compiler bug. The second template argument should be a lambda as well. When I added the following lines to test() pragma(msg, typeof(fn1)); pragma(msg, typeof(fn2)); the output is different: void delegate() system void()
That is for the version of calling test with one lamdba and one function? (`test!(() => bar, baz)`) Just a question: The compiler should not automatically convert those (functions) to lambdas? Interesting is this: void test(alias fn1, alias fn2)() { pragma(msg, typeof(fn1)); // void delegate() system pragma(msg, typeof(fn2)); // void() fn1(); fn2(); // Error: this for baz needs to be type Boo not type Foo } struct Foo { void foo() { test!(()=>bar, b.baz); } int i = 1337; struct Boo { int j = 3; void baz() {writeln(j);} } Boo b; void bar() {writeln(i);} } unittest { auto foo = Foo(); foo.foo(); } Looks like the compiler just assumes the context of the first delegate to be applicable for the second function?
 I think it's a bug probably related to multiple local lambdas. 
 We had similar issues in the past. Although it works as is, I 
 recommend you make the second one a lambda as well.

 Others, please confirm that it's a bug and let's create a bug 
 report.

 Ali
Jul 19 2018