advanced function binding

Moritz Warning moritzwarning at web.de
Wed Mar 28 18:25:29 PDT 2007


Hi,

thank you again!
I wasn't aware that the delegate can accept a ParameterTypeTuple
and the difference between the function type declarations.
Something I have learned, nice. :)

Anyway, one probably small problem remains; when I try to compile your code I get:

Main.d:94: Error: this for getBar needs to be type Foo not type Main.Wrapper!(Foo,getBar).Wrapper
Main.d:94: Error: cannot implicitly convert expression (&this.getBar) of type void delegate(()) to void(*)()
Main.d:65: template instance Main.Wrapper!(Foo,getBar) error instantiating

line 94 is "dg.funcptr = &Func;"
line 65 is "Wrapper!(Foo, Foo.getBar) x = new Wrapper!(Foo, Foo.getBar)();"

It seems to me the compiler assumes the base class of &Func is not Foo, but the surrounding object?! - weird.
I got rid of the second error adding cast(void(*)()), but it also leaves a bad feeling. :P

Kirk McDonald Wrote:

> D distinguishes between function types and function pointer types. That 
> is, given this:
> 
> void foo() {}
> 
> The following are different types:
> 
> typeof(foo)
> typeof(&foo)
> 
> The former is a function type, and is not actually that useful. (You 
> can't declare variables of this type, or use it as a function parameter 
> or return type.) The latter is a function pointer, and is very useful. 
> In that example, it is equivalent to the type "void function()".
> 
> If you want to get a pointer to a function in D, you MUST use the 
> address-of operator (as in &foo). Thus, the line:
>      alias typeof(Func) * FuncPtr;
> should actually be:
>      alias typeof(&Func) FuncPtr;
> 
> You are passing the function to the class as both an alias template 
> argument and a constructor argument. It is then available both as a 
> template argument, and as a member variable. This seems redundant. 
> Supplying it as a template argument is probably preferable. Furthermore, 
> experience has shown me it is wise to allow the user to explicitly 
> specify the type of the function. Thus, FuncPtr should actually be a 
> third template parameter, like this:
Same experience to me using C++. :)
> 
> class Wrapper(B, alias Func, FuncPtr = typeof(&Func)) {}
> 
> You can then dispense with the constructor and the funcptr member 
> variable entirely.
> 
> Next, do you really need to store the /converted/ arguments? Why not 
> just store the char[][], and convert the arguments when the function is 
> actually called? The class looks like this if you do that:
> 
> class Wrapper(B, alias Func, FuncPtr = typeof(&Func) {
>      alias ReturnType!(FuncPtr) R;
>      alias ParameterTypeTuple!(FuncPtr) Params;
>      char[][] args;
>      void bind(char[][] u) {
>          args = u;
>      }
>      R call(B b) {
>          R delegate(Params) dg;
>          dg.funcptr = &Func;
>          dg.ptr = cast(void*)b;
>          Params t;
>          foreach (i, arg; t) {
>              t[i] = convert!(typeof(arg))(this.args[i]);
>          }
>          return dg(t);
>      }
> }
> 
> Note that std.bind is not needed at all if it is done this way.
> 
> -- 
> Kirk McDonald
> http://kirkmcdonald.blogspot.com
> Pyd: Connecting D and Python
> http://pyd.dsource.org



More information about the Digitalmars-d-learn mailing list