Thread overview
DIP 1011 library alternative
May 15, 2018
Jonathan Marler
May 15, 2018
Ali Çehreli
May 15, 2018
Jonathan M Davis
May 15, 2018
Mike Franklin
May 16, 2018
Jonathan Marler
May 15, 2018
Hello, I was reviewing again DIP 1011 and investigated a library solution. That led to

https://gist.github.com/run-dlang/18845c9df3d73e45c945feaccfebfcdc

It builds on the opening examples in:

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md

I'm displeased at two aspects of the implementation:

* Perfect forwarding is tedious to implement: note that makeDelegate hardcodes void as the return type and (int, float) as parameter types. Ideally it should accept any parameters that the alias passes.

* Pass-by-alias and overloading interact poorly. Does anyone know how to refer by alias to one specific overload?


Thanks,

Andrei
May 15, 2018
On Tuesday, 15 May 2018 at 21:25:05 UTC, Andrei Alexandrescu wrote:
> Hello, I was reviewing again DIP 1011 and investigated a library solution. That led to
>
> https://gist.github.com/run-dlang/18845c9df3d73e45c945feaccfebfcdc
>
> It builds on the opening examples in:
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>
> I'm displeased at two aspects of the implementation:
>
> * Perfect forwarding is tedious to implement: note that makeDelegate hardcodes void as the return type and (int, float) as parameter types. Ideally it should accept any parameters that the alias passes.
>
> * Pass-by-alias and overloading interact poorly. Does anyone know how to refer by alias to one specific overload?
>
>
> Thanks,
>
> Andrei

thought this was dead...good to see you're looking into it :)
May 15, 2018
For convenience:

  https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md

Ali

May 15, 2018
On Tuesday, May 15, 2018 17:25:05 Andrei Alexandrescu via Digitalmars-d wrote:
> * Pass-by-alias and overloading interact poorly. Does anyone know how to refer by alias to one specific overload?

AFAIK, the only way that something like that could be done would be to use __traits(getOverloads, ...) to get at the correct overload, which is a bit of a pain, and I _think_ that it only works if the function isn't templated.

- Jonathan M Davis

May 15, 2018
On Tuesday, 15 May 2018 at 22:26:54 UTC, Jonathan M Davis wrote:

> I _think_ that it only works if the function isn't templated.

A PR to remove that limitation has been submitted at https://github.com/dlang/dmd/pull/8195, but once again, we're waiting on someone from the top to give it their blessing.

Mike

May 16, 2018
On Tuesday, 15 May 2018 at 21:25:05 UTC, Andrei Alexandrescu wrote:
> Hello, I was reviewing again DIP 1011 and investigated a library solution. That led to
>
> https://gist.github.com/run-dlang/18845c9df3d73e45c945feaccfebfcdc
>
> It builds on the opening examples in:
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>
> I'm displeased at two aspects of the implementation:
>
> * Perfect forwarding is tedious to implement: note that makeDelegate hardcodes void as the return type and (int, float) as parameter types. Ideally it should accept any parameters that the alias passes.
>
> * Pass-by-alias and overloading interact poorly. Does anyone know how to refer by alias to one specific overload?
>
>
> Thanks,
>
> Andrei

Now that I've had a chance to look the example you've shared, the only comment I'd make is that DIP1011 aims to allow applications to create "delegate-compatible" functions that don't require generating a wrapper function to forward a delegate call to the function at runtime  In this example, 2 functions have been defined that take a class and a struct pointer as the first argument, however, these function are not ABI compatible with the delegate ABI meaning you will have to generate a runtime "conversion" function to forward a delegate call to call the function.

extern(delegate) allows the application to generate the function using the delegate ABI in the first place so no "conversion" is necessary. To achieve this with a libary solution, you need to modify the function definition itself, not just create a wrapper around it.
May 17, 2018
On Tuesday, 15 May 2018 at 21:25:05 UTC, Andrei Alexandrescu wrote:
> Hello, I was reviewing again DIP 1011 and investigated a library solution. That led to
>
> https://gist.github.com/run-dlang/18845c9df3d73e45c945feaccfebfcdc
>
> It builds on the opening examples in:
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>
> I'm displeased at two aspects of the implementation:
>
> * Perfect forwarding is tedious to implement: note that makeDelegate hardcodes void as the return type and (int, float) as parameter types. Ideally it should accept any parameters that the alias passes.
>
> * Pass-by-alias and overloading interact poorly. Does anyone know how to refer by alias to one specific overload?
>
>
> Thanks,
>
> Andrei

While you are at it, could you add a linkage type that lets one specify marshaled member function callbacks for interfacing with callbacks in windows API?

In many windows callbacks they require specifying a function pointer for a standard winapi function. The problem is that we cannot pass methods of objects  to windows functions wanting a callback since the methods use the calling convention of passing in object reference as the first parameter and expects that value to point to the object the method is acting in.

I have hacked together thunking using the standard methods to allow member functions but it is not pretty.

You can get more details of the problem here:

https://www.codeproject.com/Articles/16785/Thunking-in-Win-Simplifying-Callbacks-to-Non-sta


The idea would be to allow marking methods in a certain way which thunks them automatically for passing in to winapi callbacks almost as seamless as passing a static function.

It's a little tricky to do because the object reference as to be stored somewhere and retried correctly. In my hacked code I create a new function on the heap for each callback and store the object reference along side it. Inside the function it gets it's reference not from the hidden this parameter but from from the stored object value.

The real problem is the argument layout. Winapi will expect the first argument to be it's own but it stores the value in the object reference parameter. All these nuisances can be hidden by compiler magic.




May 17, 2018
On 05/15/2018 08:44 PM, Jonathan Marler wrote:
> On Tuesday, 15 May 2018 at 21:25:05 UTC, Andrei Alexandrescu wrote:
>> Hello, I was reviewing again DIP 1011 and investigated a library solution. That led to
>>
>> https://gist.github.com/run-dlang/18845c9df3d73e45c945feaccfebfcdc
>>
>> It builds on the opening examples in:
>>
>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>>
>> I'm displeased at two aspects of the implementation:
>>
>> * Perfect forwarding is tedious to implement: note that makeDelegate hardcodes void as the return type and (int, float) as parameter types. Ideally it should accept any parameters that the alias passes.
>>
>> * Pass-by-alias and overloading interact poorly. Does anyone know how to refer by alias to one specific overload?
>>
>>
>> Thanks,
>>
>> Andrei
> 
> Now that I've had a chance to look the example you've shared, the only comment I'd make is that DIP1011 aims to allow applications to create "delegate-compatible" functions that don't require generating a wrapper function to forward a delegate call to the function at runtime  In this example, 2 functions have been defined that take a class and a struct pointer as the first argument, however, these function are not ABI compatible with the delegate ABI meaning you will have to generate a runtime "conversion" function to forward a delegate call to call the function.

Affirmative. The important matter here is the number of indirect calls, which is not increased; forwarding direct calls are often easy to inline and even if not are cheap (subject to the number and size of their arguments).

> extern(delegate) allows the application to generate the function using the delegate ABI in the first place so no "conversion" is necessary. To achieve this with a libary solution, you need to modify the function definition itself, not just create a wrapper around it.

Affirmative. But that's just stating it. The question is how needed and useful that is.

At the least, this feedback prompts for changes the rationale and motivation of the DIP. The bulk of the current rationale rests on use cases and the disadvantages of inferior workarounds. (The consistency with UFCS rewrites argument is weaker but valid, and stays.) The DIP's rationale would need to be redone to compare the proposed feature with the best known library solution (derived from the proof of concept in this thread), and them build an argument that it is needed based on (a) remaining disadvantages of the library solution and (b) convenience for frequent/intensive use.

We're not rejecting the DIP outright but we point out that it needs rework in wake of this new evidence of competing alternatives. Feel free to reach out privately for further discussion.


Thanks,

Andrei