Thread overview
Generic Delegate
Jan 17, 2005
Ben Hinkle
Jan 17, 2005
Ben Hinkle
Jan 17, 2005
Russ Lewis
Jan 17, 2005
Russ Lewis
Jan 17, 2005
Ben Hinkle
January 17, 2005
Is there anyway of having a delegate collection of different types? When I want to call one I have to cast it to the correct type (I can use TypeInfo to store information on return and arguments types).

For example:

class Bar {
   void f1() { }

   int f2(int arg) { return arg; }

   //generic delegate container

   GenericDelegate[] _generic;

}

Thanks,
Miguel Ferreira Simoes


January 17, 2005
I found that I cannot convert delegate to void*.
Is there any special reason?
Or the reason is just... you shouldn't program type unsafe?

(Probably I am missing something. But I would like to have this feature.)

Thanks.


January 17, 2005
In article <csg6g8$15k3$1@digitaldaemon.com>, Miguel Ferreira Simões says...
>
>I found that I cannot convert delegate to void*.
>Is there any special reason?
>Or the reason is just... you shouldn't program type unsafe?
>
>(Probably I am missing something. But I would like to have this feature.)
>
>Thanks.
>
>

A delegate stores 2 pointers: one to the object and one to the function. The object becomes "this" inside the function. So you can't cast it to void* since the sizes are different.

-Ben


January 17, 2005
Thanks.
So it's impossible to have a generic delegate (pointer), isn't it?
Or is there any way to wrap all kind of possible delegates?

Miguel


January 17, 2005
"Miguel Ferreira Simões" <Kobold@netcabo.pt> wrote in message news:csgj0h$1jq3$1@digitaldaemon.com...
> Thanks.
> So it's impossible to have a generic delegate (pointer), isn't it?
> Or is there any way to wrap all kind of possible delegates?
>
> Miguel
>
>

I'm not really sure what you mean by "generic". Your initial post didn't actually use the _generic member so I'm guessing at some point you add f1 and f2 to _generic. Maybe try something like

import std.stdio;
alias void delegate() GenericDelegate;
alias int delegate(int arg) SpecificDelegate;

class Bar {
   void f1() { writefln("in f1"); }
   int f2(int arg) { return arg; }
   //generic delegate container
   GenericDelegate[] _generic;
}

int main() {
  Bar x = new Bar;
  x._generic ~= &x.f1;
  x._generic ~= cast(GenericDelegate)&x.f2;

  x._generic[0]();
  SpecificDelegate y = cast(SpecificDelegate)x._generic[1];
  writefln(y(123));
  return 0;
}


January 17, 2005
Thanks!!

That's what I need!


January 17, 2005
Miguel Ferreira Simões wrote:
> Is there anyway of having a delegate collection of different types?
> When I want to call one I have to cast it to the correct type (I can use TypeInfo to store information on return and arguments types).
> 
> For example:
> 
> class Bar {
>    void f1() { }
> 
>    int f2(int arg) { return arg; }
> 
>    //generic delegate container
> 
>    GenericDelegate[] _generic;
> 
> }

When you mix two delegates that have different argument lists, you have trouble because one is expecting an argument while another is not.  If you call the one that expects arguments, and don't pass it one, something is going to go very wrong.  Likewise if you pass an argument to a delegate which doesn't expect it.

You can get around this by declaring a struct which stores both your delegate, and the argument you want to pass into it:



struct DelegateArgumentRemover(Tret,Targ) {
  Tret delegate(Targ) original_delegate;
  Targ saved_argument;

  Tret opCall() {
    return original_delegate(saved_argument);
  }
}
template RemoveArgument(Tret,Targ) {
  Tret delegate() RemoveArgument(Tret delegate(Targ) delegate,
                                 Targ arg) {
    DelegateArgumentRemover!(Tret,Targ) *temp =
               new DelegateArgumentRemover!(Tret,Targ);
    temp.original_delegate = delegate;
    temp.saved_argument = arg;
    return &temp.opCall;
  }
}



void fn1() { ... };
void fn2(int arg) { ... };

void delegate()[] delegates;
delegates.length = 2;
delegates[0] = &fn1;
delegates[1] = RemoveArgument!(void,int).RemoveArgument(&fn2, 1234);

January 17, 2005
I'm getting despaired! :(

The problem is the following...
I am trying to write "method.forName" support.
Every callable method registers itself in the constructor.

Then I want to call a method with this syntax:
    methodRead(char[] name, ...)

methodRead should know the right arguments of the method (information must be stored during the registry process).

But I am not sure if this is possible in D... does anybody have a clue?

Thanks a lot!
Miguel


January 17, 2005
Miguel Ferreira Simões wrote:
> I'm getting despaired! :(
> 
> The problem is the following...
> I am trying to write "method.forName" support.
> Every callable method registers itself in the constructor.
> 
> Then I want to call a method with this syntax:
>     methodRead(char[] name, ...)
> 
> methodRead should know the right arguments of the method (information must be stored during the registry process).
> 
> But I am not sure if this is possible in D... does anybody have a clue?

In D (just like in C or C++), the *caller* of a varargs function must use a predefined number & type of arguments.  You can't just construct a varargs on the fly.  (Well, perhaps you could, if you knew enough about the internal design, but that's not very reliable or portable.)

If you really want to pass arguments of varying types, perhaps you should define a wrapper type?  You could pass an array of structs, where each struct represents an argument.  Each struct has information that lets you determine both its type and its value.

January 17, 2005
"Miguel Ferreira Simões" <Kobold@netcabo.pt> wrote in message news:csgn22$1ops$1@digitaldaemon.com...
> I'm getting despaired! :(
>
> The problem is the following...
> I am trying to write "method.forName" support.
> Every callable method registers itself in the constructor.
>
> Then I want to call a method with this syntax:
>     methodRead(char[] name, ...)
>
> methodRead should know the right arguments of the method (information must be stored during the registry process).
>
> But I am not sure if this is possible in D... does anybody have a clue?
>
> Thanks a lot!
> Miguel
>
>

You might want to check out std.loader which gives an API for looking up symbols from executable and shared libraries. You'll have to do the name mangling by hand, I think since the loader code just hands the symbol name to the OS to look up and it doesn't have any idea about D's name mangling. Once you get a pointer to the function you'll have to cook up the stack - also not trivial as Russ points out.

Basically, D doesn't have an reflection API.