Jump to page: 1 2
Thread overview
Re: Calling an alias for a Class method in another scope
Jun 01, 2012
d coder
Jun 01, 2012
Jacob Carlborg
Jun 01, 2012
d coder
Jun 01, 2012
Jacob Carlborg
Jun 01, 2012
Mehrdad
Jun 01, 2012
d coder
Jun 01, 2012
d coder
Jun 01, 2012
d coder
Jun 01, 2012
Jacob Carlborg
Jun 01, 2012
Jacob Carlborg
Jun 01, 2012
d coder
Jun 02, 2012
Max Samukha
Jun 02, 2012
Max Samukha
Jun 02, 2012
d coder
June 01, 2012
Hello All

Particularly I would like to know if it is possible at all in D to invoke a class method transferred to a scope outside the class as an alias argument.

Regards
- Puneet


June 01, 2012
On Friday, 1 June 2012 at 12:32:55 UTC, d coder wrote:
> Hello All
>
> Particularly I would like to know if it is possible at all in D to invoke a
> class method transferred to a scope outside the class as an alias argument.
>
> Regards
> - Puneet

I think it should work, if I understand correctly what you want to do.

--
/Jacob Carlborg
June 01, 2012
On Fri, 01 Jun 2012 08:32:02 -0400, d coder <dlang.coder@gmail.com> wrote:

> Hello All
>
> Particularly I would like to know if it is possible at all in D to invoke a
> class method transferred to a scope outside the class as an alias argument.

Is it possible?  Yes.  But not easy.  I won't go into the details, but suffice to say, you must reconstruct a delegate and then call it.

D does not have "pointers to members" like C++ does.  So when you alias f.foo you are actually aliasing the function F.foo (without the context pointer, and without a parameter to be able to place it).

However, there is another way -- use delegates:

void main() {
  Foo f = new Foo();
  auto dg = &f.foo; // need to make a symbol so it can be aliased
  callfoo!(dg)();
}

Sorry if this is disappointing, D is not as low-level in this area.  But if you are willing to always pair a member function with its context pointer, delegates are much simpler and more useful than pointers to members:

void main() {
   Foo f = new Foo;
   auto dg = &f.foo;
   dg();
}

-Steve
June 01, 2012
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. But it works when I say:

void main() {
  Foo f = new Foo();
  callfoo!(() {f.foo();})(f);
}

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.

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).

Regards
- Puneet


June 01, 2012
On 2012-06-01 15:25, d coder 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. But it works when I say:
>
> void main() {
>    Foo f = new Foo();
>    callfoo!(() {f.foo();})(f);
> }
>
> 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.
>
> 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).
>
> Regards
> - Puneet
>

Originally you said "class method", so I was thinking like this:

class Foo
{
    static void bar ()
    {
        writeln("bar");
    }
}

void foo (alias m) ()
{
    m();
}

void main ()
{
    foo!(Foo.bar);
}

But if you actually mean "instance method" you need to use delegates and possible compose them as Steven showed.

-- 
/Jacob Carlborg
June 01, 2012
On Fri, 01 Jun 2012 09:25:57 -0400, d coder <dlang.coder@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
June 01, 2012
Another way to phrase it would be that D is forcing you to to use templates where they really aren't meant to be used. :\
June 01, 2012
Hello Steve


> There is a way, as I hinted :)
>
> I'll show you how, but be prepared to deal with ugliness!
>

All this smart code would be hidden from the end-users so I really do not care.


> 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
>
> Let me understand this. Is F here an alias for foo? If so why I need to
mention stuff like &F.foo? It would defeat my purpose if I have to mention foo by name. But the code you have put here does give me hope. Just that I am not able to grasp what F and foo represent here. Probably you mean F is the type of the class that instantiates the template and foo is the alias for the method I want to call. Am I right?


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

For my purpose that is perfectly fine for now.

Thanks for throwing light on delegates. You have shown me hope :)

- Regards
- Puneet


June 01, 2012
On 2012-06-01 15:51, Steven Schveighoffer wrote:
> On Fri, 01 Jun 2012 09:25:57 -0400, d coder <dlang.coder@gmail.com> wrote:
>> 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.

That can't work since there is no this-reference for "foo"?

-- 
/Jacob Carlborg
June 01, 2012
On Fri, 01 Jun 2012 10:09:49 -0400, d coder <dlang.coder@gmail.com> wrote:

> Hello Steve
>
>
>> There is a way, as I hinted :)
>>
>> I'll show you how, but be prepared to deal with ugliness!
>>
>
> All this smart code would be hidden from the end-users so I really do not
> care.
>
>
>> 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
>>
>> Let me understand this. Is F here an alias for foo? If so why I need to
> mention stuff like &F.foo?

Sorry!  I meant Foo, not F.  F should be replaced with whatever the class type is.

-Steve
« First   ‹ Prev
1 2