Perfect forwarding

Petar Petar
Thu Jul 30 04:56:55 UTC 2020


On Wednesday, 29 July 2020 at 16:31:08 UTC, Jean-Louis Leroy 
wrote:
> On Wednesday, 29 July 2020 at 16:11:02 UTC, Petar Kirov 
> [ZombineDev] wrote:
>> On Wednesday, 29 July 2020 at 12:54:36 UTC, Adam D. Ruppe 
>> wrote:
>>> On Wednesday, 29 July 2020 at 10:38:29 UTC, Manu wrote:
>>>> On Wed, Jul 29, 2020 at 9:40 AM Jean-Louis Leroy via
>>>>> Guaranteed failure then? ;-)
>>>>
>>>> Yes.
>>>
>>> What's wrong with my solution earlier in the thread?
>>
>> That it uses a string mixin :P
>>
>> What Manu is arguing is that if parameter storage classes were 
>> instead proper type qualifiers, then one could trivially 
>> manipulate them with std.meta. And then supposedly there would 
>> be no need to string mixins at all.
>
> If we go back to the original problem, you still need a string 
> mixin to inject the function name in two places.
>
> As for Adam's solution, it solves a slightly different problem 
> but I don't see why he uses a string mixin:
>
> template forward(alias fun)
> {
>     import std.traits;
>     @(__traits(getAttributes, fun)) auto ref 
> forward(Parameters!fun args) {
>         return fun(args);
>     }
> }
>
> @(42) void myfun(int, ref double x, out string s);
>
> pragma(msg, typeof(forward!myfun));
> // void function(int _param_0, ref double _param_1, out string 
> _param_2) @system
> pragma(msg, __traits(getAttributes, forward!myfun));
> // tuple(42)
>
> Anyway, storage classes are not a difficulty, as long as you 
> use the whole __parameters, or slice it (__parameters[0..1]), 
> and refrain from indexing it (__parameters[0] loses storage 
> classes). Strange beast...

My point, that you can't do much useful processing with 
`__parameters` (except pass all of subset of it), still stands.

Say you have a function with N parameters. Some of those 
parameters are integers and may have a UDA attached to them that 
specifies the minimum and maximum value they may receive. For 
example:

R fun(
   scope P1 arg1,
   return int* arg2,
   lazy @intetval(-16, 320) long arg3,
   @interval(0, 127) uint arg4,
   ref @interval(0, 8192) size_t arg5
);

The task is create a template, which given a function type like 
typeof(&fun) returns a new function type with all integer 
parameters replaced by the smallest type that is big enough to 
hold the interval specified by the UDA and preserves all storage 
classes.


R hun(
   scope P1 arg1,
   return int* arg2,
   lazy @intetval(-16, 320) short arg3,
   @interval(0, 127) ubyte arg4,
   ref @interval(0, 8192) ushort arg5
);

The way I'd like to go about solving this is like this:

template TightenIntegerParams(Fun)
{
   alias TightenIntegerParams =
     ReturnType!Fun function(
       staticMap!(
         TightenParam,
         Parameters!Fun
       )
     );
}

However the moment staticMap internally does `Args[i]` in order 
to pass the i-th element to the mapping function `F` we lose all 
information about the storage classes and UDAs.



More information about the Digitalmars-d mailing list