www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Code doesn't compile

reply Mohammad Sadegh Khoeini <mskco.tp gmail.com> writes:
Hi D community,

I was just playing with some code and encountered a problem:

```
struct Foo(alias T)
{
   void call() { T(); }
}

struct Bar
{
   void fun() {}
}

struct Baz(T)
{
   void fun(U)() {}
}

void main()
{
   auto b = Bar();
   auto f = Foo!(delegate{b.fun();})();  // this works
   f.call();
   auto foobaz = &b.fun;
   auto t = Foo!(foobaz)();  // this works
   // auto u = Foo!(&b.fun)();  // doesn't work: vaiable b cannot be 
read at compile time
   // auto v = Foo!(Baz!int.fun!int)();  //doesn't work: this for fun 
needs to be type Baz not type Foo!(fun)
}
```

I wonder if this is a bug or I'm doing it wrong!

I'm using "DMD64 D Compiler v2.063" on Mac OS X 10.8
Jul 05 2013
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 5 July 2013 at 11:23:55 UTC, Mohammad Sadegh Khoeini 
wrote:
   // auto u = Foo!(&b.fun)();  // doesn't work: vaiable b 
 cannot be read at compile time
   // auto v = Foo!(Baz!int.fun!int)();  //doesn't work: this 
 for fun needs to be type Baz not type Foo!(fun)

Not a bug, I think at least, getting the address needs to be done at runtime and delegates need an address. The reason the literal works is literals can cheat at figuring out its variables. Wrapping it like you did for variable f is the easiest way to make it work.
Jul 05 2013
parent Mohammad Sadegh Khoeini <mskco.tp gmail.com> writes:
On 7/5/13 7:05 PM, Adam D. Ruppe wrote:
 On Friday, 5 July 2013 at 11:23:55 UTC, Mohammad Sadegh Khoeini wrote:
   // auto u = Foo!(&b.fun)();  // doesn't work: vaiable b cannot be
 read at compile time
   // auto v = Foo!(Baz!int.fun!int)();  //doesn't work: this for fun
 needs to be type Baz not type Foo!(fun)

Not a bug, I think at least, getting the address needs to be done at runtime and delegates need an address. The reason the literal works is literals can cheat at figuring out its variables. Wrapping it like you did for variable f is the easiest way to make it work.

Yes, but it's confusing. What is great about D's meta programming is that it is very intuitive. However, the gotchas like that will surprise people. specifically that these kind of stuff can happen in the middle of a very complex code, which makes it very hard to find out the source of the problem. I feel like the compiler in these kind of situations should be able to deduce on itself that &b.fun needs to wrapped on the site of its appearance. The other side of this problem is how can I cheat the templating system so it would accept these kind of expressions?
Jul 05 2013
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 5 July 2013 at 15:17:09 UTC, Mohammad Sadegh Khoeini 
wrote:
 However, the gotchas like that will surprise people.

Aye, I have fought with it before and never made a good solution. The problem is that b can change at runtime, so it has no way of knowing for sure which object it should use at compile time. It does work easily if you use it as a runtime delegate though, without being a template at all, or a type template like this: import std.traits; void call(T)(T t) if(isCallable!T) { t(); } then call(&foo) and so on should all work.
 The other side of this problem is how can I cheat the 
 templating system so it would accept these kind of expressions?

I don't know any more though :( maybe someone else has some good tricks.
Jul 05 2013