Parameter forwarding

Kostiantyn Tokar tokarkonstantyn at yandex.ua
Thu Oct 14 16:53:17 UTC 2021


Hello.

I'm concerned about D's move semantics and how Phobos supports 
it. For example, `std.typecons.Tuple`.
```d
struct A
{
     int i;
     this(this) { writeln("Expensive copy"); }
}

void main()
{
     auto t = Tuple!(A)(A(42));
}
```
This code produces 1 unnecessary copy. Argument is an rvalue and 
can be passed by move. Indeed, one copy is elided when rvalue 
argument binds to constructor parameter, but then it became an 
lvalue. 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.

But it gets even worse, because factory function `tuple` creates 
another level of indirection and produces 2 copies from an rvalue.

C++'s tuples perform perfect forwarding. If class implements a 
move constructor, then neither tuple's constructor nor 
`make_tuple` produce copies. 
[Example](https://onlinegdb.com/sz0NhNNf2). Price for that is 
separate move constructor, but at least there is a way to avoid 
copying.

But this pattern is common in Phobos. This UFCS chain produces 17 
copies. But should it?
```d
only(A(0), A(1), A(2))
         .filter!(a => a.i == 1)
         .takeOne
         .front;
```
[Code](https://run.dlang.io/is/thEFC2)

So is there no way to utilize move semantics using Phobos? Why 
forwarding is so neglected?


More information about the Digitalmars-d-learn mailing list