Parameter forwarding

Kostiantyn Tokar tokarkonstantyn at yandex.ua
Fri Oct 15 07:28:37 UTC 2021


On Thursday, 14 October 2021 at 17:37:21 UTC, Paul Backus wrote:
> On Thursday, 14 October 2021 at 16:53:17 UTC, Kostiantyn Tokar 
> wrote:
>> Take a look at `Tuple` 
>> [constructor](https://github.com/dlang/phobos/blob/4130a1176cdb6111b0c26c7c53702e10011ff067/std/typecons.d#L672).
>> ```d
>> this(Types values)
>> {
>>     field[] = values[];
>> }
>> ```
>> Actual fields are constructed from lvalues. Why there is no 
>> `auto ref` and `forward`? It looks like there is no way to 
>> construct a tuple without copying.
>
> Poor test coverage. If you go through Phobos and test 
> everything with a non-copyable struct (`@disable this(this)`), 
> you will find that most templates (including `Tuple`) fail to 
> compile. It is simply a case that the authors of the code never 
> considered.
>
>> So is there no way to utilize move semantics using Phobos? Why 
>> forwarding is so neglected?
>
> I suspect it is neglected because nobody wants to volunteer for 
> the tedious work of going through Phobos, adding unit tests 
> that check for unnecessary copies, and inserting `auto ref` and 
> `forward` in the appropriate places.

I see. So there should be forwarding, but it is not implemented.

The problem I see is that there is no simple solution for 
forwarding members of an aggregate. For example,
```d
void foo()(auto ref A a, auto ref B b)
{
     pragma(msg, __traits(isRef, a));
     pragma(msg, __traits(isRef, b));
}
void bar(Tuple!(A, B) t)
{
     foo(forward!t.expand); // true, true - no move
}
```
Do I need something like `forward`, but for fields of a parameter?
```d
template forwardMember(alias arg, string member)
{
     static if (__traits(isRef,  arg) ||
                __traits(isOut,  arg) ||
                __traits(isLazy, arg) ||
                !is(typeof(move(__traits(getMember, arg, 
member)))))
         @property auto ref forwardMember(){ return 
__traits(getMember, arg, member); }
     else
         @property auto forwardMember(){ return 
move(__traits(getMember, arg, member)); }
}
```
`forwardMember` doesn't work for `Tuple.expand` though. I didn't 
tried to make it more general, maybe some mixins are required.

Doesn't forwarding members separately breaks anything?


More information about the Digitalmars-d-learn mailing list