Calling an alias for a Class method in another scope

Steven Schveighoffer schveiguy at yahoo.com
Fri Jun 1 06:51:01 PDT 2012


On Fri, 01 Jun 2012 09:25:57 -0400, d coder <dlang.coder at gmail.com> wrote:

> Hello Steve, thanks for looking at this.
>
> I see the code works when I create the delegate first and then send it to
> template.  That is the way you do it here.
>
>
>> void main() {
>>  Foo f = new Foo();
>>  auto dg = &f.foo; // need to make a symbol so it can be aliased
>>  callfoo!(dg)();
>> }
>>
>>
> But it does not work when I put &f.foo directly as the template argument.

That is correct.  An alias cannot accept an *expression*, it can only  
accept a *symbol*.

> But it works when I say:
>
> void main() {
>   Foo f = new Foo();
>   callfoo!(() {f.foo();})(f);
> }

This is because a delegate literal (lambda) is an implicit symbol and an  
expression at the same time.  I think it's actually a special case for  
alias.

Note that this is not as efficient, because you have a delegate that then  
calls a member function, whereas the version I gave calls the member  
function directly

> But that still does not solve my problem. In my real code, I want to send
> the delegate to a template class. And I am supposed to do that as a  
> member
> of another class. So the code looks something like:
>
> Class Bar(alias F) {
>  // Call F in some function here
> }
>
> Class Foo {
>   void foo();
>   Bar!(() {foo();}) bar;
> }
>
> Again this does not work. Maybe I am expecting too much from D. :-) I am
> somewhat aware of the issues involved here. I have seen some earlier D
> threads.

lambdas cannot exist outside a function scope.  This is a limitation of D  
that has been pointed out before, and I think it should be made available,  
but don't hold your breath :)  D is just starting to get more filled out  
in the area of lambdas.

>
> But then I thought there might be a way to pass the method function  
> literal
> (foo) and separately the this pointer of Foo object and then combine the
> two at the other end (inside Bar).

There is a way, as I hinted :)

I'll show you how, but be prepared to deal with ugliness!

typeof(&F.init.foo) dg; // alternately: void delegate() dg;
dg.funcptr = &F.foo;    // use the type, not the instance, to get the  
function pointer itself instead of a delegate
dg.ptr = cast(void *)f; // set f is the context pointer

dg(); // now should call f.foo

Note that this is *not* a virtual call.  That is currently impossible to  
do without using a lambda.

-Steve


More information about the Digitalmars-d mailing list