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