Thread overview
Two functions with different args. Taking address of the one
Mar 11, 2021
Paul Backus
Mar 11, 2021
Paul Backus
Mar 11, 2021
Dennis
Mar 11, 2021
Adam D. Ruppe
March 11, 2021
Have:
    void process( ref MouseKeyEvent event )
    {
       ...
    }

    void process( ref MouseMoveEvent event )
    {
       ...
    }

Want:
    _processMouseKey  = &process; // <-- not works
    _processMouseMove = &process; // <-- not works

What is correct way to get address of function with specific argument ?

March 11, 2021
On Thursday, 11 March 2021 at 12:26:07 UTC, Виталий Фадеев wrote:
> Have:
>     void process( ref MouseKeyEvent event )
>     {
>        ...
>     }
>
>     void process( ref MouseMoveEvent event )
>     {
>        ...
>     }
>
> Want:
>     _processMouseKey  = &process; // <-- not works
>     _processMouseMove = &process; // <-- not works
>
> What is correct way to get address of function with specific argument ?

You can use __traits(getOverloads, process) plus some metaprogramming to get the address of a specific overload. But IMO the easiest way is to use lambdas:

    __processMouseKey = (ref MouseKeyEvent event) { process(event); };
    __processMouseMove = (ref MouseMoveEvent event) { process(event); };
March 11, 2021
On Thursday, 11 March 2021 at 12:48:13 UTC, Paul Backus wrote:
> On Thursday, 11 March 2021 at 12:26:07 UTC, Виталий Фадеев wrote:
>> Have:
>>     void process( ref MouseKeyEvent event )
>>     {
>>        ...
>>     }
>>
>>     void process( ref MouseMoveEvent event )
>>     {
>>        ...
>>     }
>>
>> Want:
>>     _processMouseKey  = &process; // <-- not works
>>     _processMouseMove = &process; // <-- not works
>>
>> What is correct way to get address of function with specific argument ?
>
> You can use __traits(getOverloads, process) plus some metaprogramming to get the address of a specific overload. But IMO the easiest way is to use lambdas:
>
>     __processMouseKey = (ref MouseKeyEvent event) { process(event); };
>     __processMouseMove = (ref MouseMoveEvent event) { process(event); };

This will generate lambda:
  __processMouseKey = (ref MouseKeyEvent event) { process(event); };

two calls:
  call labnda;
    call process;

What right way to call function directly with selecting one of two ?

March 11, 2021
On Thursday, 11 March 2021 at 12:56:34 UTC, Виталий Фадеев wrote:
>
> This will generate lambda:
>   __processMouseKey = (ref MouseKeyEvent event) { process(event); };
>
> two calls:
>   call labnda;
>     call process;
>
> What right way to call function directly with selecting one of two ?

Something like this:

    template Overloads(alias symbol)
    {
        static if (__traits(compiles, __traits(parent, symbol)))
            alias Overloads = __traits(getOverloads,
                __traits(parent, symbol),
                __traits(identifier, symbol)
            );
        else
            alias Overloads = symbol;
    }

    auto getOverloadFor(alias fun, T)()
    {
        foreach (overload; Overloads!fun)
            static if (__traits(compiles, (T arg) { overload(arg); }))
                return &overload;
    }

Usage:

    __processMouseKey = getOverloadFor!(process, MouseKeyEvent);
March 11, 2021
On Thursday, 11 March 2021 at 12:56:34 UTC, Виталий Фадеев wrote:
> What right way to call function directly with selecting one of two ?

If they are not nested functions, you can also do:
```
// Separate names
void processKey (ref MouseKeyEvent event) {...}
void processMove(ref MouseMoveEvent event) {...}

// Still create overload set
alias process = processKey;
alias process = processMove;

_processMouseKey  = &processKey;
_processMouseMove = &processMove;
```

March 11, 2021
On Thursday, 11 March 2021 at 13:14:56 UTC, Paul Backus wrote:
> On Thursday, 11 March 2021 at 12:56:34 UTC, Виталий Фадеев wrote:
>> [...]
>
> Something like this:
>
>     template Overloads(alias symbol)
>     {
>         static if (__traits(compiles, __traits(parent, symbol)))
>             alias Overloads = __traits(getOverloads,
>                 __traits(parent, symbol),
>                 __traits(identifier, symbol)
>             );
>         else
>             alias Overloads = symbol;
>     }
>
>     auto getOverloadFor(alias fun, T)()
>     {
>         foreach (overload; Overloads!fun)
>             static if (__traits(compiles, (T arg) { overload(arg); }))
>                 return &overload;
>     }
>
> Usage:
>
>     __processMouseKey = getOverloadFor!(process, MouseKeyEvent);

Thanks a lot, bro!
March 11, 2021
On Thursday, 11 March 2021 at 12:26:07 UTC, Виталий Фадеев wrote:
>     _processMouseKey  = &process; // <-- not works
>     _processMouseMove = &process; // <-- not works

This *should* actually work. What type are those variables?

struct MouseKeyEvent {}
struct MouseMoveEvent{}
void process( ref MouseKeyEvent event ) { }
void process( ref MouseMoveEvent event ) { }

void main() {
      // this works because the type is given on the left
      // so the compiler knows which overload works
        void function(ref MouseMoveEvent) processMouseMove = &process;
}
March 11, 2021
On Thursday, 11 March 2021 at 14:23:39 UTC, Adam D. Ruppe wrote:
> On Thursday, 11 March 2021 at 12:26:07 UTC, Виталий Фадеев wrote:
>>     _processMouseKey  = &process; // <-- not works
>>     _processMouseMove = &process; // <-- not works
>
> This *should* actually work. What type are those variables?
>
> struct MouseKeyEvent {}
> struct MouseMoveEvent{}
> void process( ref MouseKeyEvent event ) { }
> void process( ref MouseMoveEvent event ) { }
>
> void main() {
>       // this works because the type is given on the left
>       // so the compiler knows which overload works
>         void function(ref MouseMoveEvent) processMouseMove = &process;
> }

I was stupid.
It is really simple!

Thank a lot, bro!