An issue with setting delegates via templates

Christophe travert at phare.normalesup.org
Thu Oct 27 07:16:41 PDT 2011


Andrej Mitrovic , dans le message (digitalmars.D.learn:30286), a écrit :
> class Foo
> {
>     void func(double) { }
>     void func(int) { }
> 
>     void set(T)(T handler) { dg = handler; }
>     void delegate(int) dg;
> }
> 
> void main()
> {
>     auto foo = new Foo;
>     foo.set(&foo.func);  // NG, func(double) is picked up first
> }
> 
> Error: cannot implicitly convert expression (handler) of type void
> delegate(double _param_0) to void delegate(int)
> 
> The problem here is that `void func(double)` is declared first, and
> that's what the address-of operator picks up. If you swap the two
> overloads this sample will compile.
> 
> How could this be worked around /while still using templates/? There
> can only be one topmost function overload, so with two overloads this
> can be worked around, but with more overloads this workaround can't be
> used.
> 
> I've almost found a workaround via the getOverloads trait:
> 
> import std.traits;
> 
> class Foo
> {
>     void func(double) { }
>     void func(int) { }
> 
>     void set(T)(T handler)
>     {
>         dg = handler;
>     }
> 
>     void delegate(int) dg;
> }
> 
> void main()
> {
>     auto foo = new Foo;
>     foo.set(&__traits(getOverloads, foo, "func")[1]);
> }
> 
> This works, but I can't use this from within a template. IOW, I can't
> pass a function pointer to a template and then figure out if that
> function is actually an overload of some class. I'd need more powerful
> compile-time features for that. If I were able to do that then I could
> enumerate all the overloads and pick one if it matches the type of
> 'dg'. It's kind of overkill but it could work, at least theoretically.
> 
> Otherwise I'd really need a way to explicitly specify which function
> overload to pass when I use the address-of operator, but that would
> probably have to be a language feature.


Once you are inside set, handler is just a function and context pointer 
pair. Finding out what are the overloads of handler just with it's 
adress will be very complicated for a very limitted usage. Maybe an 
approach would be to make handler an alias rather than a delegate (but 
this won't work here because you have to pass foo along with 
&Foo.func...).

Why does Foo.set has to be a template ?
The obvious workarround is to make set expect a void delegate(int), 
instead of an undefined type, since this is the only type you can assign 
to dg.

I think I need a better example to understand why set is a template, and 
how to work arround that.



More information about the Digitalmars-d-learn mailing list